nexus-agents 2.128.3 → 2.128.5
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/dist/{chunk-SH6JG7GE.js → chunk-6CDAMT2O.js} +13 -10
- package/dist/{chunk-SH6JG7GE.js.map → chunk-6CDAMT2O.js.map} +1 -1
- package/dist/{chunk-AOVWC7LS.js → chunk-GPH6YSNB.js} +7 -3
- package/dist/chunk-GPH6YSNB.js.map +1 -0
- package/dist/{chunk-ND7FZ53Q.js → chunk-NSKECFYS.js} +2 -2
- package/dist/{chunk-3Y2OKEHQ.js → chunk-PSV5NRXH.js} +53 -6
- package/dist/{chunk-3Y2OKEHQ.js.map → chunk-PSV5NRXH.js.map} +1 -1
- package/dist/cli.js +4 -4
- package/dist/{consensus-vote-NXBPAPFW.js → consensus-vote-RT3DJYEI.js} +2 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -4
- package/dist/{setup-command-C6MGIEZJ.js → setup-command-P2HHAW7Q.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-AOVWC7LS.js.map +0 -1
- /package/dist/{chunk-ND7FZ53Q.js.map → chunk-NSKECFYS.js.map} +0 -0
- /package/dist/{consensus-vote-NXBPAPFW.js.map → consensus-vote-RT3DJYEI.js.map} +0 -0
- /package/dist/{setup-command-C6MGIEZJ.js.map → setup-command-P2HHAW7Q.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/tools/consensus-vote.ts","../src/cli/vote-types.ts","../src/cli-adapters/codex-limits.ts","../src/cli/voter-prompts.ts","../src/cli/voter-response.ts","../src/cli/voter-execution.ts","../src/cli/voter-agents-deadline.ts","../src/cli/voter-agents.ts","../src/consensus/types-voting-protocol.ts","../src/consensus/types-weighted-voting.ts","../src/consensus/higher-order-types.ts","../src/consensus/higher-order-helpers.ts","../src/consensus/higher-order-voting.ts","../src/consensus/strategies.ts","../src/consensus/result-builder.ts","../src/consensus/helpers.ts","../src/consensus/incremental-quorum.ts","../src/consensus/engine.ts","../src/consensus/quorum-validator.ts","../src/consensus/voting-protocol-helpers.ts","../src/consensus/voting-protocol.ts","../src/agents/collaboration/byzantine-events.ts","../src/consensus/weighted-voting-helpers.ts","../src/consensus/weighted-voting.ts","../src/consensus/correlation-helpers.ts","../src/consensus/correlation-tracker.ts","../src/consensus/correlation-persistence.ts","../src/mcp/tools/consensus-vote-types.ts","../src/mcp/tools/consensus-vote-error-policy.ts","../src/orchestration/outcomes/outcome-store-persistence.ts","../src/mcp/tools/consensus-vote-recording.ts","../src/mcp/tools/consensus-vote-signals.ts","../src/mcp/tools/simulation-guard.ts","../src/mcp/jobs/job-result-store.ts","../src/mcp/jobs/job-idempotency.ts","../src/mcp/jobs/job-concurrency.ts","../src/mcp/jobs/run-as-job.ts"],"sourcesContent":["/* eslint-disable max-lines */ // Consensus voting — cohesive single module (governance: 400-600 OK)\n/**\n * nexus-agents/mcp - Consensus Vote Tool\n * @module mcp/tools/consensus-vote\n */\n\nimport { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ILogger } from '../../core/index.js';\nimport {\n createLogger,\n getErrorMessage,\n getTimeProvider,\n getRandomProvider,\n formatZodError,\n} from '../../core/index.js';\nimport type { IMcpNotifier } from '../mcp-notifier.js';\nimport { createMcpNotifier, NOOP_NOTIFIER, withProgressHeartbeat } from '../mcp-notifier.js';\nimport {\n wrapToolWithTimeout,\n toSdkCallbackWithBudgetCheck,\n getToolTimeout,\n} from '../middleware/tool-wrapper.js';\nimport { createSecureHandler, type HandlerContext } from '../middleware/secure-handler.js';\nimport {\n toolStructuredError,\n toolSuccess,\n type ToolResult,\n type BaseMcpToolDeps,\n} from './tool-result.js';\nimport type { ConsensusAlgorithm, Vote, ConsensusResult, Proposal } from '../../consensus/types.js';\nimport { SUPERMAJORITY_THRESHOLD } from '../../consensus/types-core.js';\nimport type { VoterRole, AgentVoteResult } from '../../cli/vote-types.js';\nimport { collectRealVotes } from '../../cli/voter-agents.js';\nimport { createConsensusEngine } from '../../consensus/engine.js';\nimport type {\n HigherOrderVotingResult,\n ICorrelationTracker,\n} from '../../consensus/higher-order-types.js';\nimport { HigherOrderVotingStrategy } from '../../consensus/index.js';\nimport {\n createPersistentCorrelationTracker,\n createPersistedProposal,\n saveCorrelationData,\n} from '../../consensus/correlation-persistence.js';\nimport {\n MAX_PROPOSAL_LENGTH,\n VotingStrategySchema,\n VoteThresholdSchema,\n ConsensusVoteInputSchema,\n buildResponse,\n getDefaultErrorPolicy,\n isHigherOrderStrategy,\n shouldEscalateLowPosterior,\n} from './consensus-vote-types.js';\nimport { applyErrorPolicy } from './consensus-vote-error-policy.js';\nimport { recordVoteSuccess, recordVoteError } from './consensus-vote-recording.js';\nimport { emitVoteRejectedSignal } from './consensus-vote-signals.js';\nimport { getPipelineEventBus } from '../../pipeline/event-bus.js';\nimport { warnIfSimulatedOutsideTests } from './simulation-guard.js';\nimport { getToolAnnotations } from '../tool-annotations.js';\n// #3045 / epic #2631 Stage 4 — async-mode dispatch + concurrency cap.\n// #3045 / epic #2631 Stage 4 — async-mode dispatch via the shared `runAsJob`\n// helper (#3729).\nimport { runAsJob } from '../jobs/run-as-job.js';\nimport { randomUUID } from 'node:crypto';\nimport type {\n VotingStrategy,\n ConsensusVoteInput,\n ConsensusVoteResponse,\n ExtendedVotingResult,\n} from './consensus-vote-types.js';\n\nexport type {\n VotingStrategy,\n ConsensusVoteInput,\n ConsensusVoteResponse,\n AgentVoteSummary,\n VoteDecisionStatus,\n HigherOrderMetadata,\n ExtendedVotingResult,\n} from './consensus-vote-types.js';\nexport { VotingStrategySchema, ConsensusVoteInputSchema } from './consensus-vote-types.js';\n\n// --- Correlation Tracker Singleton ---\n//\n// Lifecycle & memory model (documented per #3169):\n// * SCOPE: one process-wide, lazily-created instance shared by every\n// `consensus_vote` call. It accumulates cross-proposal voter agreement so\n// the higher_order strategy can down-weight correlated (redundant) voters.\n// One shared tracker is intentional — correlation signal is only useful\n// pooled across proposals.\n// * PERSISTENCE: backed by `createPersistentCorrelationTracker()`, which\n// hydrates from / appends to the on-disk correlation store, so the signal\n// survives restarts (the in-memory map is a hot cache over that store).\n// * MEMORY BOUND: NOT unbounded. The underlying `CorrelationTracker` is\n// FIFO-bounded by `maxProposals` / `maxObservationsPerAgent` (#521) —\n// oldest proposals are evicted once the cap is hit (eviction is logged at\n// debug in `correlation-tracker.ts`, so memory pressure is observable).\n// * RESET: `resetCorrelationTracker()` drops the instance; the next\n// `getOrCreateCorrelationTracker()` rebuilds it (re-hydrating from disk).\n// Test-isolation only. There is intentionally no per-milestone \"reset\n// between cycles\" coordinator API — eviction already bounds growth, and\n// clearing history mid-run would discard the signal the strategy needs.\nlet persistentCorrelationTracker: ICorrelationTracker | undefined;\n\n/**\n * Gets or creates the process-wide persistent CorrelationTracker (#517).\n * See the lifecycle / memory-bound / reset notes above the declaration (#3169).\n */\nfunction getOrCreateCorrelationTracker(): ICorrelationTracker {\n persistentCorrelationTracker ??= createPersistentCorrelationTracker();\n return persistentCorrelationTracker;\n}\n\n/**\n * Drops the singleton so the next {@link getOrCreateCorrelationTracker} rebuilds\n * it (re-hydrating from the persistent store). Test-isolation only. @internal\n */\nexport function resetCorrelationTracker(): void {\n persistentCorrelationTracker = undefined;\n}\n\n// --- Dependencies ---\nexport interface ConsensusVoteDeps extends BaseMcpToolDeps {\n /** MCP notifier for client-visible logging (Issue #974) */\n notifier?: IMcpNotifier | undefined;\n}\n\n// --- Strategy Resolution ---\nfunction resolveStrategy(input: ConsensusVoteInput): VotingStrategy {\n if (input.strategy !== undefined) return input.strategy;\n if (input.threshold !== undefined) {\n switch (input.threshold) {\n case 'majority':\n return 'simple_majority';\n case 'supermajority':\n return 'supermajority';\n case 'unanimous':\n return 'unanimous';\n }\n }\n return 'simple_majority';\n}\n\nfunction strategyToAlgorithm(strategy: VotingStrategy): ConsensusAlgorithm {\n if (strategy === 'higher_order') return 'higher_order';\n if (strategy === 'opinion_wise') return 'opinion_wise';\n return strategy;\n}\n\nfunction getVoterRoles(quickMode: boolean): readonly VoterRole[] {\n // Default panel expanded to 7 roles 2026-04-25 — scope_steward added to\n // catch build-vs-buy blind spots (#2185). QuickMode substitutes\n // scope_steward for pm so fast triage covers existence-justification.\n return quickMode\n ? ['architect', 'security', 'scope_steward']\n : ['architect', 'security', 'devex', 'ai_ml', 'pm', 'catfish', 'scope_steward'];\n}\n\n// --- Voting Execution ---\n/** Creates a synthetic ConsensusResult when all votes are errors (Issue #815). */\nfunction createEmptyConsensusResult(\n proposal: string,\n algorithm: ConsensusAlgorithm\n): ConsensusResult {\n const now = new Date().toISOString();\n return {\n proposalId: 'no-valid-votes',\n proposal: { title: 'MCP Consensus Vote', description: proposal, algorithm },\n outcome: 'rejected',\n votes: new Map<string, Vote>(),\n voteCounts: { approve: 0, reject: 0, abstain: 0, total: 0 },\n approvalPercentage: 0,\n quorumReached: false,\n startedAt: now,\n closedAt: now,\n durationMs: 0,\n };\n}\n\n/**\n * Creates a synthetic ConsensusResult for an error-policy short-circuit\n * (#2630). Reused for both the hard floor (errors > 50%) and `fail_closed`.\n * Stamps the reason on the proposal title and, since #3124, reports the TRUE\n * vote breakdown of the responding (non-error) voters instead of all-zeros —\n * the outcome stays `rejected` (the policy failed closed), but the counts and\n * `approvalPercentage` are honest (e.g. 6 approvals + 1 error → approve:6,\n * 100%) so callers/audit can see the policy short-circuited a real consensus\n * rather than mistake it for a genuine rejection.\n */\nexport function createPolicyFailedResult(\n proposal: string,\n algorithm: ConsensusAlgorithm,\n reason: string,\n votes: readonly AgentVoteResult[]\n): ConsensusResult {\n const now = new Date().toISOString();\n const voteMap = new Map<string, Vote>();\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n for (const v of votes) {\n if (v.source === 'error') continue; // errors surface separately, not as a decision\n voteMap.set(v.role, v.vote);\n if (v.vote.decision === 'approve') approve++;\n else if (v.vote.decision === 'reject') reject++;\n else abstain++;\n }\n const responding = approve + reject + abstain;\n return {\n proposalId: 'error-policy-short-circuit',\n proposal: { title: `MCP Consensus Vote — ${reason}`, description: proposal, algorithm },\n outcome: 'rejected',\n votes: voteMap,\n voteCounts: { approve, reject, abstain, total: responding },\n approvalPercentage: responding > 0 ? (approve / responding) * 100 : 0,\n quorumReached: false,\n startedAt: now,\n closedAt: now,\n durationMs: 0,\n };\n}\n\n/** Thresholds per algorithm for cascade detection. */\nconst CASCADE_THRESHOLDS: Record<string, number> = {\n majority: 0.5,\n supermajority: SUPERMAJORITY_THRESHOLD,\n unanimous: 1.0,\n};\n\n/** Detect if vote outcome is mathematically decided (#1765). */\nfunction detectEarlyCascade(\n algorithm: string,\n approvals: number,\n rejections: number,\n total: number\n): { decided: boolean; reason: string } {\n const threshold = CASCADE_THRESHOLDS[algorithm] ?? 0.5;\n if (total === 0) return { decided: false, reason: '' };\n\n // Unanimous: any rejection decides\n if (algorithm === 'unanimous' && rejections > 0) {\n return { decided: true, reason: `Unanimous rejected: ${String(rejections)} rejection(s)` };\n }\n // Approval locked: even if all remaining vote reject, approval holds\n if (approvals / total > threshold) {\n return {\n decided: true,\n reason: `Approval locked: ${String(approvals)}/${String(total)} > ${String(threshold)}`,\n };\n }\n // Rejection locked: even if all remaining vote approve, rejection holds\n const remaining = total - approvals - rejections;\n if ((approvals + remaining) / total < threshold) {\n return {\n decided: true,\n reason: `Rejection locked: max possible ${String(approvals + remaining)}/${String(total)} < ${String(threshold)}`,\n };\n }\n return { decided: false, reason: '' };\n}\n\n/**\n * Run the consensus engine over already-policy-applied votes.\n *\n * Callers MUST pass `engineVotes` produced by `applyErrorPolicy` (#2630)\n * — under `reduce_denominator` that means errors are already filtered;\n * under `count_as_abstain` errors have been converted to abstain\n * decisions but kept in the array. This function does no further\n * filtering on `source`.\n */\nasync function processVotesThroughEngine(\n engineVotes: readonly AgentVoteResult[],\n proposal: string,\n algorithm: ConsensusAlgorithm\n): Promise<ConsensusResult> {\n if (engineVotes.length === 0) return createEmptyConsensusResult(proposal, algorithm);\n\n const engine = createConsensusEngine();\n const engineProposal: Proposal = {\n title: 'MCP Consensus Vote',\n description: proposal,\n algorithm,\n };\n const proposalResult = await engine.propose(engineProposal);\n if (!proposalResult.ok)\n throw new Error(`Failed to create proposal: ${proposalResult.error.message}`, {\n cause: proposalResult.error,\n });\n\n const proposalId = proposalResult.value;\n for (const { role, vote } of engineVotes) await engine.vote(proposalId, role, vote);\n\n const resultRes = await engine.close(proposalId);\n if (!resultRes.ok)\n throw new Error(`Failed to close proposal: ${resultRes.error.message}`, {\n cause: resultRes.error,\n });\n return resultRes.value;\n}\n\nfunction runHigherOrderVoting(\n strategy: VotingStrategy,\n voteMap: Map<string, Vote>,\n logger: ILogger\n): HigherOrderVotingResult | undefined {\n if (!isHigherOrderStrategy(strategy)) return undefined;\n const hovStrategy = new HigherOrderVotingStrategy();\n const tracker = getOrCreateCorrelationTracker();\n const result = hovStrategy.aggregate(voteMap, tracker);\n logger.info('Higher-Order Voting complete', {\n method: result.method,\n decision: result.decision,\n posteriorApproval: result.posteriorApproval.toFixed(3),\n });\n return result;\n}\n\nfunction recordVotesToTracker(\n votes: readonly AgentVoteResult[],\n outcome: 'approved' | 'rejected',\n logger: ILogger\n): void {\n // #3170: record the REAL (LLM) votes even when the panel is mixed-source,\n // rather than dropping ALL correlation data because one voter simulated/errored.\n // Recording the accurate LLM-only subset beats leaving the matrix permanently stale.\n const llmVotes = votes.filter((v) => v.source === 'llm');\n if (llmVotes.length < votes.length) {\n logger.warn('Recording only LLM votes to correlation tracker; excluding non-LLM votes', {\n recorded: llmVotes.length,\n excluded: votes.length - llmVotes.length,\n });\n }\n if (llmVotes.length === 0) return; // nothing real to record\n const llmVoteMap = new Map<string, Vote>();\n for (const v of llmVotes) llmVoteMap.set(v.role, v.vote);\n\n const tracker = getOrCreateCorrelationTracker();\n const id = `consensus-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;\n tracker.recordProposalVotes(id, llmVoteMap, outcome);\n logger.debug('Recorded votes to tracker', { proposalId: id, outcome });\n\n try {\n const persisted = createPersistedProposal(id, llmVoteMap, outcome);\n const saveResult = saveCorrelationData([persisted]);\n if (!saveResult.ok) {\n logger.warn('Failed to persist correlation data', { error: saveResult.error.message });\n }\n } catch (error: unknown) {\n const message = getErrorMessage(error);\n logger.warn('Error persisting correlation data', { error: message });\n }\n}\n\n/** Process votes with cascade detection — extracted for max-lines-per-function (#1765). */\n/**\n * Run the engine + cascade-detection + higher-order voting against\n * already-policy-applied votes (#2630).\n *\n * Callers MUST pass `engineVotes` produced by `applyErrorPolicy` — no\n * filtering on `source` happens inside this function. Cascade-detection\n * counts and the higher-order voteMap are both built directly from\n * `engineVotes`.\n */\nasync function processVotesWithCascade(\n engineVotes: readonly AgentVoteResult[],\n opts: {\n totalRoles: number;\n proposal: string;\n algorithm: ConsensusAlgorithm;\n strategy: VotingStrategy;\n log: ILogger;\n }\n): Promise<{\n engineResult: ConsensusResult;\n voteMap: Map<string, Vote>;\n higherOrderResult: ReturnType<typeof runHigherOrderVoting>;\n outcome: 'approved' | 'rejected';\n cascaded: boolean;\n}> {\n const approvals = engineVotes.filter((v) => v.vote.decision === 'approve').length;\n const rejections = engineVotes.filter((v) => v.vote.decision === 'reject').length;\n const cascadeInfo = detectEarlyCascade(opts.algorithm, approvals, rejections, opts.totalRoles);\n\n if (cascadeInfo.decided) {\n opts.log.info('Vote cascade: outcome decided early', {\n approvals,\n rejections,\n total: opts.totalRoles,\n reason: cascadeInfo.reason,\n });\n }\n\n const engineResult = await processVotesThroughEngine(engineVotes, opts.proposal, opts.algorithm);\n const voteMap = new Map<string, Vote>();\n for (const { role, vote } of engineVotes) voteMap.set(role, vote);\n\n const higherOrderResult = cascadeInfo.decided\n ? undefined\n : runHigherOrderVoting(opts.strategy, voteMap, opts.log);\n const outcome: 'approved' | 'rejected' =\n engineResult.outcome === 'approved' ? 'approved' : 'rejected';\n\n return { engineResult, voteMap, higherOrderResult, outcome, cascaded: cascadeInfo.decided };\n}\n\n/** Execute a consensus vote with full strategy support. Exported for pipeline DRY (#1694). */\n/** Confidence threshold above which a contrarian rejection triggers escalation (#1799). */\nconst CONTRARIAN_ESCALATION_THRESHOLD = 0.8;\n\n/** Run a single contrarian agent to check for YAGNI/MISALIGNED/SECURITY_RISK (#1799). */\nasync function runContrarianCheck(\n proposal: string,\n log: ILogger\n): Promise<{ shouldEscalate: boolean; reason: string; confidence: number }> {\n try {\n const { executeExpert } = await import('../../pipeline/expert-bridge.js');\n const prompt = [\n 'You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.',\n 'Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.',\n '',\n `Proposal: ${proposal.slice(0, 2000)}`,\n '',\n 'If you find a strong reason to reject, respond with JSON:',\n '{\"decision\":\"reject\",\"confidence\":0.0-1.0,\"reasoning\":\"your concern\"}',\n 'If the proposal is sound, respond with:',\n '{\"decision\":\"approve\",\"confidence\":0.0-1.0,\"reasoning\":\"why it is acceptable\"}',\n ].join('\\n');\n\n const result = await executeExpert('architecture', prompt);\n if (!result.success) return { shouldEscalate: false, reason: '', confidence: 0 };\n\n const jsonMatch = result.text.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch === null) return { shouldEscalate: false, reason: '', confidence: 0 };\n\n const parsed = JSON.parse(jsonMatch[0]) as {\n decision?: string;\n confidence?: number;\n reasoning?: string;\n };\n\n const isRejection = parsed.decision === 'reject';\n const confidence = typeof parsed.confidence === 'number' ? parsed.confidence : 0;\n const reasoning = typeof parsed.reasoning === 'string' ? parsed.reasoning : '';\n\n if (isRejection && confidence >= CONTRARIAN_ESCALATION_THRESHOLD) {\n log.info('Contrarian rejected with high confidence', {\n confidence,\n reasoning: reasoning.slice(0, 200),\n });\n return { shouldEscalate: true, reason: reasoning, confidence };\n }\n\n return { shouldEscalate: false, reason: '', confidence };\n } catch (error: unknown) {\n // Closes #2952 (medium): pre-fix the bare `catch {}` swallowed\n // `executeExpert` failures, JSON parse errors, and expert-bridge\n // import errors identically — the escalation guardrail silently\n // disabled itself with no log trail. Log + return the default\n // \"no escalation\" envelope so a contrarian-check infrastructure\n // bug is at least visible in operator logs.\n const message = error instanceof Error ? error.message : String(error);\n log.warn('Contrarian check failed; defaulting to no escalation', { error: message });\n return { shouldEscalate: false, reason: '', confidence: 0 };\n }\n}\n\n/**\n * Build a short-circuit result for the error-policy gate (#2630). Called\n * when the hard floor (>50% errors) trips or `fail_closed` matches.\n * Logs the warning and returns the synthetic `ExtendedVotingResult` that\n * `executeVoting` propagates to the response builder.\n */\nfunction buildPolicyShortCircuitResult(args: {\n input: ConsensusVoteInput;\n strategy: VotingStrategy;\n algorithm: ConsensusAlgorithm;\n votes: readonly AgentVoteResult[];\n errorPolicy: ConsensusVoteInput['errorPolicy'];\n reason: string;\n startTime: number;\n logger: ILogger;\n}): ExtendedVotingResult {\n args.logger.warn('Consensus vote short-circuited by error policy', {\n errorPolicy: args.errorPolicy,\n reason: args.reason,\n });\n const totalTimeMs = getTimeProvider().now() - args.startTime;\n return {\n proposal: args.input.proposal,\n threshold: args.algorithm,\n result: createPolicyFailedResult(args.input.proposal, args.algorithm, args.reason, args.votes),\n votes: args.votes,\n totalTimeMs,\n simulateVotes: args.input.simulateVotes,\n strategy: args.strategy,\n // #3124: surface WHY a high-approval result is still 'rejected' so callers\n // don't mistake a fail-closed policy short-circuit for a genuine rejection.\n policyReason: args.reason,\n };\n}\n\n/**\n * Escalation gate for `quickMode` approvals. Two independent triggers, both\n * re-running `executeVoting` with the full voter panel:\n *\n * 1. Posterior-confidence (#3174): for `higher_order`/`opinion_wise`, a borderline\n * Bayesian posterior (below `HIGHER_ORDER_ESCALATION_POSTERIOR_FLOOR`) means the\n * 3-voter quick panel was barely decisive — escalate without spending a\n * contrarian call. Checked first so a borderline posterior short-circuits it.\n * 2. Contrarian agent (#1799): run a single contrarian to catch\n * YAGNI / SECURITY_RISK / SCOPE_CREEP; escalate if it rejects with high\n * confidence.\n *\n * Returns the escalated result, or `undefined` for \"no escalation, continue\n * with the quickMode result.\"\n */\nasync function maybeEscalateContrarian(\n input: ConsensusVoteInput,\n outcome: 'approved' | 'rejected',\n ctx: { strategy: VotingStrategy; posteriorApproval: number | undefined },\n logger: ILogger,\n opts?: { voteTimeoutMs?: number }\n): Promise<ExtendedVotingResult | undefined> {\n if (!input.quickMode || outcome !== 'approved' || input.simulateVotes) return undefined;\n\n if (shouldEscalateLowPosterior(ctx.strategy, outcome, input.quickMode, ctx.posteriorApproval)) {\n logger.warn('Posterior-confidence escalation: re-running with full vote (#3174)', {\n strategy: ctx.strategy,\n posteriorApproval: ctx.posteriorApproval,\n });\n return executeVoting({ ...input, quickMode: false }, logger, opts);\n }\n\n const escalation = await runContrarianCheck(input.proposal, logger);\n if (!escalation.shouldEscalate) return undefined;\n logger.warn('Contrarian escalation: re-running with full vote', {\n reason: escalation.reason,\n confidence: escalation.confidence,\n });\n return executeVoting({ ...input, quickMode: false }, logger, opts);\n}\n\n/*\n * Top-level voting flow: vote collection → error-policy gate → engine +\n * cascade → contrarian escalation → finalize. Further extraction\n * obscures control flow more than it helps; helpers already extracted\n * are applyErrorPolicy, buildPolicyShortCircuitResult,\n * maybeEscalateContrarian, finalizeVotingResult.\n */\n// eslint-disable-next-line max-lines-per-function -- see block comment above\nexport async function executeVoting(\n input: ConsensusVoteInput,\n logger: ILogger,\n opts?: { voteTimeoutMs?: number }\n): Promise<ExtendedVotingResult> {\n const strategy = resolveStrategy(input);\n const algorithm = strategyToAlgorithm(strategy);\n const roles = getVoterRoles(input.quickMode);\n const startTime = getTimeProvider().now();\n const errorPolicy = input.errorPolicy ?? getDefaultErrorPolicy(strategy);\n\n logger.info('Starting consensus vote', {\n strategy,\n algorithm,\n roleCount: roles.length,\n errorPolicy,\n });\n const votes = await collectRealVotes({\n roles,\n proposal: input.proposal,\n simulate: input.simulateVotes,\n ...(opts?.voteTimeoutMs !== undefined && { timeoutMs: opts.voteTimeoutMs }),\n });\n\n // Error-policy gate (#2630): hard floor + fail_closed + reduce_denominator /\n // count_as_abstain transformation. Engine sees the resulting shape.\n const policyDecision = applyErrorPolicy(votes, errorPolicy);\n if (policyDecision.shortCircuit) {\n return buildPolicyShortCircuitResult({\n input,\n strategy,\n algorithm,\n votes,\n errorPolicy,\n reason: policyDecision.reason ?? 'error policy short-circuit',\n startTime,\n logger,\n });\n }\n\n // Check for early cascade and process votes (#1765)\n const { engineResult, higherOrderResult, outcome, cascaded } = await processVotesWithCascade(\n policyDecision.engineVotes,\n {\n totalRoles: roles.length,\n proposal: input.proposal,\n algorithm,\n strategy,\n log: logger,\n }\n );\n\n recordVotesToTracker(votes, outcome, logger);\n\n const escalated = await maybeEscalateContrarian(\n input,\n outcome,\n { strategy, posteriorApproval: higherOrderResult?.posteriorApproval },\n logger,\n opts\n );\n if (escalated !== undefined) return escalated;\n\n return finalizeVotingResult({\n input,\n strategy,\n algorithm,\n engineResult,\n higherOrderResult,\n votes,\n outcome,\n cascaded,\n startTime,\n logger,\n });\n}\n\n/**\n * Run a consensus vote with a plain goal as the proposal, default settings\n * (real voters, default strategy). The strategy executor the unified `run`\n * entry point dispatches to for the `consensus` strategy (#3575). Non-simulated.\n */\nexport async function runConsensusForGoal(\n goal: string,\n logger: ILogger = createLogger({ tool: 'consensus_vote' })\n): Promise<ExtendedVotingResult> {\n // Parse through the schema so defaults (quickMode, simulateVotes:false) apply.\n return executeVoting(ConsensusVoteInputSchema.parse({ proposal: goal }), logger);\n}\n\n/** Build the final `ExtendedVotingResult` once the engine + cascade settle. */\nfunction finalizeVotingResult(args: {\n input: ConsensusVoteInput;\n strategy: VotingStrategy;\n algorithm: ConsensusAlgorithm;\n engineResult: ConsensusResult;\n higherOrderResult: ReturnType<typeof runHigherOrderVoting>;\n votes: readonly AgentVoteResult[];\n outcome: 'approved' | 'rejected';\n cascaded: boolean;\n startTime: number;\n logger: ILogger;\n}): ExtendedVotingResult {\n const totalTimeMs = getTimeProvider().now() - args.startTime;\n args.logger.info('Consensus vote completed', {\n strategy: args.strategy,\n outcome: args.outcome,\n durationMs: totalTimeMs,\n cascaded: args.cascaded,\n });\n const result: ExtendedVotingResult = {\n proposal: args.input.proposal,\n threshold: args.algorithm,\n result: args.engineResult,\n votes: args.votes,\n totalTimeMs,\n simulateVotes: args.input.simulateVotes,\n strategy: args.strategy,\n };\n if (args.higherOrderResult !== undefined) result.higherOrderResult = args.higherOrderResult;\n return result;\n}\n\n// --- Handler & Registration ---\nasync function handleConsensusVote(\n deps: ConsensusVoteDeps,\n args: ConsensusVoteInput\n): Promise<{ ok: true; value: ConsensusVoteResponse } | { ok: false; error: string }> {\n const logger = deps.logger ?? createLogger({ tool: 'consensus_vote' });\n if (args.simulateVotes) warnIfSimulatedOutsideTests('consensus_vote', logger);\n try {\n const result = await executeVoting(args, logger);\n const strategy = args.strategy ?? 'simple_majority';\n\n // Detect all-error votes: return structured error instead of fake \"rejected\" (#1552)\n const errorVotes = result.votes.filter((v) => v.source === 'error');\n if (errorVotes.length === result.votes.length && result.votes.length > 0) {\n const failures = errorVotes.map((v) => `${v.role}: ${v.error ?? 'unknown error'}`).join('; ');\n logger.warn('All voters failed', { failureCount: errorVotes.length, failures });\n recordVoteError(args.proposal, `All ${String(errorVotes.length)} voters failed: ${failures}`);\n return {\n ok: false,\n error: `All ${String(errorVotes.length)} voters failed. Failures: ${failures}`,\n };\n }\n\n recordVoteSuccess(\n args.proposal,\n strategy,\n result.result.outcome,\n result.totalTimeMs,\n result.votes\n );\n // Close the self-tuning loop: a rejected vote emits signal.vote_rejected\n // onto the typed pipeline bus for the shadow TuneStage (#3147; #3289 Option 2).\n emitVoteRejectedSignal(result.result, getPipelineEventBus(), logger);\n return { ok: true, value: buildResponse(args, result) };\n } catch (error) {\n const message = getErrorMessage(error);\n const cause = error instanceof Error ? error : new Error(message);\n logger.error('Consensus vote failed', cause);\n recordVoteError(args.proposal, message);\n return { ok: false, error: `Voting failed: ${message}` };\n }\n}\n\ntype ConsensusVoteToolResponse = ToolResult;\n\n/**\n * Dispatch the vote on a background promise + return a pending envelope\n * (#3045 / epic #2631 Stage 4). Mirrors run_workflow / orchestrate.\n *\n * Cancellation semantics: when `cancel_job` lands while the vote is\n * in-flight, the existing collector unwinds via the AbortSignal plumbing\n * already in #3038 — `collectRealVotes` honors per-voter signals — and\n * the dispatcher writes whatever partial vote set landed before the\n * abort signal as the job result. That preserves audit visibility into\n * who voted before the cancel happened, instead of throwing away all\n * the work.\n *\n * Concurrency cap is enforced via `tryAcquire('consensus_vote')`\n * (default 2; voting is 7-fan-out so caps multiply adapter load fast).\n */\nfunction dispatchAsyncConsensusVote(\n deps: ConsensusVoteDeps,\n args: import('./consensus-vote-types.js').ConsensusVoteInput\n): ConsensusVoteToolResponse {\n // #3729: dispatch via the shared `runAsJob` helper — the exact sequence this\n // function used to inline. consensus_vote's only diff is the freshJobId; its\n // pending/busy/replay/collision envelopes are byte-for-byte the helper's\n // ToolResult defaults, so no per-tool `toEnvelope` is needed.\n return runAsJob<\n import('./consensus-vote-types.js').ConsensusVoteInput,\n Awaited<ReturnType<typeof handleConsensusVote>>\n >({\n toolName: 'consensus_vote',\n input: args,\n idempotencyKey: args.idempotencyKey,\n freshJobId: () => `job-vote-${randomUUID()}`,\n run: (_jobId, input) => handleConsensusVote(deps, input),\n ...(deps.logger !== undefined ? { logger: deps.logger } : {}),\n });\n}\n\n/**\n * Run the synchronous vote path + format the response. Extracted from\n * the handler so the async-mode branch keeps the per-function size cap\n * (#3045 added a branch + dispatcher call site to the handler).\n */\nasync function runSyncConsensusVote(\n deps: ConsensusVoteDeps,\n notifier: IMcpNotifier,\n args: import('./consensus-vote-types.js').ConsensusVoteInput\n): Promise<ConsensusVoteToolResponse> {\n const result = await withProgressHeartbeat('consensus_vote', notifier, () =>\n handleConsensusVote(deps, args)\n );\n if (!result.ok) {\n return toolStructuredError({ errorCategory: 'internal', message: result.error });\n }\n for (const vote of result.value.votes) {\n notifier.debug('consensus_vote', {\n event: 'vote_collected',\n role: vote.role,\n decision: vote.decision,\n });\n }\n notifier.info('consensus_vote', {\n event: 'vote_complete',\n decision: result.value.decision,\n approvalPercentage: result.value.approvalPercentage,\n voteCount: result.value.votes.length,\n });\n const data = result.value as unknown as Record<string, unknown>;\n return {\n ...toolSuccess(JSON.stringify(result.value, null, 2)),\n structuredContent: data,\n };\n}\n\nfunction createConsensusVoteHandler(deps: ConsensusVoteDeps) {\n const notifier = deps.notifier ?? NOOP_NOTIFIER;\n return async (args: unknown, ctx: HandlerContext): Promise<ConsensusVoteToolResponse> => {\n const validationResult = ConsensusVoteInputSchema.safeParse(args);\n if (!validationResult.success) {\n return toolStructuredError({\n errorCategory: 'validation',\n message: `Validation error: ${formatZodError(validationResult.error)}`,\n });\n }\n const strategy = validationResult.data.strategy ?? 'simple_majority';\n ctx.logger.debug('Starting consensus vote', {\n strategy,\n quickMode: validationResult.data.quickMode,\n ...(validationResult.data.mode !== undefined ? { mode: validationResult.data.mode } : {}),\n });\n notifier.info('consensus_vote', {\n event: 'vote_start',\n proposalLength: validationResult.data.proposal.length,\n strategy,\n });\n // #3045 / epic #2631 Stage 4 — async-mode dispatch.\n if (validationResult.data.mode === 'async') {\n const asyncResult = dispatchAsyncConsensusVote(deps, validationResult.data);\n notifier.info('consensus_vote', {\n event: 'vote_dispatched_async',\n proposalLength: validationResult.data.proposal.length,\n strategy,\n });\n return asyncResult;\n }\n return runSyncConsensusVote(deps, notifier, validationResult.data);\n };\n}\n\n/** Output schema for consensus_vote tool (Issue #1117, #1246). */\nexport const CONSENSUS_VOTE_OUTPUT_SCHEMA = {\n proposal: z.string(),\n strategy: VotingStrategySchema,\n decision: z.enum(['approved', 'rejected', 'no_quorum']),\n approvalPercentage: z.number(),\n voteCounts: z.object({\n approve: z.number(),\n reject: z.number(),\n abstain: z.number(),\n error: z.number(),\n }),\n votes: z.array(\n z.object({\n role: z.string().max(100),\n decision: z.enum(['approve', 'reject', 'abstain']),\n confidence: z.number(),\n reasoning: z.string().max(4000),\n simulated: z.boolean(),\n error: z.boolean(),\n modelUsed: z.string().max(100).optional(),\n rejectionCategories: z\n .array(\n z.enum([\n 'YAGNI',\n 'DRY_VIOLATION',\n 'OVER_ENGINEERING',\n 'SCOPE_CREEP',\n 'SECURITY_RISK',\n 'MISALIGNED',\n 'INSUFFICIENT_EVIDENCE',\n ])\n )\n .optional(),\n })\n ),\n threshold: VoteThresholdSchema.optional(),\n durationMs: z.number(),\n simulateVotes: z.boolean(),\n higherOrderMetadata: z\n .object({\n posteriorApproval: z.number(),\n posteriorRejection: z.number(),\n effectiveVoteCount: z.number(),\n method: z.enum(['ow', 'isp', 'simple']),\n usedCorrelationData: z.boolean(),\n improvementOverBaseline: z.number(),\n downweightedAgents: z.array(z.string().max(100)).max(10),\n reasoning: z.string().max(2000),\n })\n .optional(),\n // #3124: explains a `rejected` decision that coexists with a high\n // approvalPercentage (an error-policy short-circuit, e.g. fail_closed).\n policyReason: z.string().max(200).optional(),\n};\n\n/**\n * Registers the consensus_vote tool with the MCP server.\n * Uses createSecureHandler (Issue #531) with timeout protection (Issue #271).\n * @category MCP\n */\nexport function registerConsensusVoteTool(server: McpServer, deps: ConsensusVoteDeps): void {\n const logger = deps.logger ?? createLogger({ tool: 'consensus_vote' });\n const notifier = deps.notifier ?? createMcpNotifier(server);\n const depsWithNotifier = { ...deps, notifier };\n const toolSchema = {\n proposal: z.string().min(1).max(MAX_PROPOSAL_LENGTH).describe('Proposal text to vote on'),\n threshold: z\n .enum(['majority', 'supermajority', 'unanimous'])\n .optional()\n .describe('Voting threshold (legacy). Use strategy instead.'),\n strategy: VotingStrategySchema.optional().describe(\n 'Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order'\n ),\n quickMode: z.boolean().optional().default(false).describe('Use 3 agents instead of 7'),\n simulateVotes: z\n .boolean()\n .optional()\n .default(false)\n .describe('TESTS ONLY — random output, must not be used for real decisions (#2319)'),\n };\n\n const description =\n 'Execute multi-model consensus voting on a proposal. ' +\n 'Uses 7 specialized agent roles (architect, security, devex, ai_ml, pm, catfish, scope_steward) ' +\n 'to vote on proposals with configurable strategies. ' +\n 'Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514).';\n\n const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {\n toolName: 'consensus_vote',\n rateLimiter: deps.rateLimiter,\n logger,\n });\n\n const timeoutMs = getToolTimeout('consensus_vote', deps.security);\n const wrappedHandler = wrapToolWithTimeout('consensus_vote', secureHandler, {\n timeoutMs,\n logger,\n });\n\n server.registerTool(\n 'consensus_vote',\n {\n description,\n inputSchema: toolSchema,\n outputSchema: CONSENSUS_VOTE_OUTPUT_SCHEMA,\n annotations: getToolAnnotations('consensus_vote'),\n },\n toSdkCallbackWithBudgetCheck(wrappedHandler, 'consensus_vote', timeoutMs, logger)\n );\n logger.info('Registered consensus_vote tool with secure handler and timeout protection');\n}\n","/**\n * nexus-agents vote command types\n *\n * Type definitions for the consensus voting CLI command.\n *\n * (Source: Issue #212, Process Automation Epic #209)\n */\n\nimport type { ConsensusAlgorithm, Vote, ConsensusResult } from '../consensus/types.js';\nimport type { ErrorPolicy, VoteThreshold } from '../mcp/tools/consensus-vote-types.js';\n\n/**\n * Options for the vote command.\n */\nexport interface VoteCommandOptions {\n readonly proposal: string;\n readonly threshold?: VoteThreshold;\n /** Use simulated votes instead of LLM execution (maps from --dry-run CLI flag) */\n readonly dryRun?: boolean;\n readonly quick?: boolean;\n readonly verbose?: boolean;\n readonly createIssue?: boolean;\n readonly issueNumber?: number;\n /** Timeout per vote in milliseconds (default: 90000 per Issue #607) */\n readonly timeoutMs?: number;\n /**\n * How to treat voters that errored or timed out (#2630). When undefined,\n * the same per-strategy default `executeVoting` uses applies:\n * `fail_closed` for unanimous, `reduce_denominator` otherwise.\n */\n readonly errorPolicy?: ErrorPolicy;\n}\n\n/**\n * Voter agent role definitions.\n *\n * `scope_steward` (#2185) was added 2026-04-25 to address a build-vs-buy\n * blind spot in the original 6-role panel: the panel approved a proposal\n * to build a USB-flasher CLI without flagging that Rufus already solves\n * the problem. The scope-steward role explicitly checks for existing tools\n * + biases toward \"don't build.\"\n */\nexport type VoterRole =\n | 'architect'\n | 'security'\n | 'devex'\n | 'ai_ml'\n | 'pm'\n | 'catfish'\n | 'scope_steward';\n\n/**\n * Agent role descriptions for prompt generation.\n */\nexport const VOTER_ROLES: Record<VoterRole, string> = {\n architect: 'Software Architect - evaluates technical design, scalability, and maintainability',\n security:\n 'Security Engineer - evaluates security implications, vulnerabilities, and attack vectors',\n devex: 'Developer Experience - evaluates usability, documentation, and developer workflow',\n ai_ml: 'AI/ML Engineer - evaluates AI/ML aspects, model selection, and learning capabilities',\n pm: 'Product Manager - evaluates business value, user impact, and resource allocation',\n catfish:\n 'Contrarian Analyst - deliberately challenges proposals to prevent agreement bias (arXiv:2505.21503)',\n scope_steward:\n 'Scope Steward - asks whether to build at all; checks existing tools, biases toward kill-the-feature (#2185)',\n};\n\n/**\n * Individual agent vote with metadata.\n */\nexport interface AgentVoteResult {\n readonly role: VoterRole;\n readonly vote: Vote;\n readonly processingTimeMs: number;\n /**\n * Source of the vote:\n * - 'llm': Real LLM execution\n * - 'simulation': Fallback simulation (opt-in only)\n * - 'error': Error during execution (Issue #523)\n */\n readonly source: 'llm' | 'simulation' | 'error';\n /** CLI that executed this vote (for adaptive routing feedback). */\n readonly cli?: string | undefined;\n /** Error message if vote fell back to simulation or encountered an error */\n readonly error?: string;\n}\n\n/**\n * Full voting result.\n */\nexport interface VotingResult {\n readonly proposal: string;\n readonly threshold: ConsensusAlgorithm;\n readonly result: ConsensusResult;\n readonly votes: readonly AgentVoteResult[];\n readonly totalTimeMs: number;\n /** Whether simulated votes were used instead of LLM execution */\n readonly simulateVotes: boolean;\n}\n\n/**\n * Vote verification hash for audit trail.\n */\nexport interface VoteHash {\n readonly role: VoterRole;\n readonly hash: string;\n readonly timestamp: string;\n}\n","/**\n * Codex CLI subagent limits (#2659, Epic D).\n *\n * Codex's `~/.codex/config.toml` `[agents]` section defaults to\n * `max_depth = 1` and `max_threads = 6` (verified against\n * developers.openai.com/codex config reference — the originating issue's\n * `max_thread_depth` key name was wrong).\n *\n * nexus-agents does NOT write the operator's global `~/.codex/config.toml`\n * (that would clobber operator-owned state) and does NOT silently\n * auto-flatten routing topology. Instead — Option C from the #2659 design\n * vote — it WARNS at fan-out time when a planned concurrency would exceed\n * Codex's defaults, so the operator can raise their own `[agents]` limits\n * or spread the panel across more CLIs. The two existing parallel-dispatch\n * sites are already conservative: `worker-dispatcher.ts` caps a wave at 3\n * concurrent workers, and `collectRealVotes` round-robins voter roles\n * across available CLIs. The warned case is the narrow one — a single-CLI\n * fallback where every voter role lands on Codex.\n *\n * @module cli-adapters/codex-limits\n * @see Issue #2659\n */\n\n/** Codex `[agents] max_depth` default — nested subagent depth. */\nexport const CODEX_DEFAULT_MAX_DEPTH = 1;\n\n/** Codex `[agents] max_threads` default — concurrent subagent threads. */\nexport const CODEX_DEFAULT_MAX_THREADS = 6;\n\n/**\n * A structured warning when `codexBoundConcurrency` parallel calls are\n * about to be dispatched to Codex, exceeding its default `max_threads`.\n * Returns `null` when within limits. Does not block — the operator stays\n * in control (Option C).\n */\nexport function checkCodexConcurrency(codexBoundConcurrency: number): string | null {\n if (codexBoundConcurrency <= CODEX_DEFAULT_MAX_THREADS) return null;\n return (\n `${String(codexBoundConcurrency)} parallel calls are bound for Codex, exceeding its ` +\n `default max_threads=${String(CODEX_DEFAULT_MAX_THREADS)}. Codex may queue or drop the ` +\n `excess. Raise [agents] max_threads in ~/.codex/config.toml, or spread the panel across ` +\n `more CLIs (claude/gemini) so fewer roles land on Codex.`\n );\n}\n\n/**\n * A structured warning when a planned subagent nesting `depth` exceeds\n * Codex's default `max_depth`. Returns `null` when within limits.\n */\nexport function checkCodexDepth(depth: number): string | null {\n if (depth <= CODEX_DEFAULT_MAX_DEPTH) return null;\n return (\n `planned subagent nesting depth ${String(depth)} exceeds Codex's default ` +\n `max_depth=${String(CODEX_DEFAULT_MAX_DEPTH)}. Codex will reject the nested spawn. ` +\n `Raise [agents] max_depth in ~/.codex/config.toml, or flatten the expert chain.`\n );\n}\n","/**\n * nexus-agents/cli - Voter System Prompts\n *\n * Role-specific system prompts for voter agents.\n *\n * @module cli/voter-prompts\n * (Source: Issue #226, extracted from voter-agents.ts for #272)\n */\n\nimport type { VoterRole } from './vote-types.js';\n\n/** Default project name used in voter prompts when no context is provided. */\nconst DEFAULT_PROJECT = 'nexus-agents';\n\n/**\n * Generate voter system prompts with optional project context.\n *\n * When nexus-agents MCP tools are used as a service for other projects,\n * the default \"nexus-agents project\" context causes voters to reject\n * proposals as MISALIGNED. This function allows injecting the target\n * project name so voters evaluate correctly.\n *\n * @param project - Project name/context to inject (defaults to 'nexus-agents')\n */\n/**\n * PR-review-mode addendum (#2244). Appended to every voter's prompt so the\n * format is reinforced at the system-prompt level, where role framing\n * dominates — the proposal-text-only approach in #2238 produced 0 verified\n * findings across 50 voter calls in #2241.\n *\n * The addendum is conditional on its face: voters reviewing a non-diff\n * proposal ignore it. Voters reviewing a diff get the explicit format +\n * few-shot example here, plus the same instructions in the proposal text.\n */\nfunction prReviewModeAddendum(): string {\n return `\nPR-review mode — if you are reviewing a code diff (not a proposal) AND you have at least one concrete defect that justifies blocking the merge, populate the OPTIONAL TOP-LEVEL \"findings\" field on your JSON response. NOT inside reasoning — top-level. The schema:\n\n\"findings\": [\n {\n \"summary\": \"One-line summary\",\n \"location\": \"path/file.ext:LINE\",\n \"severity\": \"critical\" | \"high\" | \"medium\" | \"low\",\n \"gate\": {\n \"reread_cited_line\": \"passed\",\n \"traced_call_path\": \"passed\",\n \"named_assertion\": \"Concrete failing assertion — what test would fail and how. Substantive, not 'passed'.\",\n \"ruled_out_language_non_issue\": \"passed\"\n },\n \"claim\": \"What is wrong and why it justifies blocking.\"\n }\n]\n\nA finding only triggers strict request_changes if all 4 gate fields = \"passed\" AND named_assertion is substantive (>10 chars naming a concrete failure, not just \"passed\"). Findings missing any of those surface as informational only — they do not block on their own. The 2026-04-25 audit (#2225) found a 100% false-positive rate when this gate wasn't enforced. If you're approving the diff, OMIT the findings field entirely. If reviewing a non-diff proposal, ignore this section.\n\nHistory note: an earlier prompt asked for YAML inside reasoning; that format was lossy across JSON serialization (#2245). Use the top-level JSON array above.`;\n}\n\n/** Common footer appended to all voter prompts. */\nfunction voterFooter(): string {\n return `\nWorkflow-test assessment (include in your reasoning):\n- Testability: Can changes be verified with automated tests?\n- Workflow integration: Does this fit existing CI/build/test pipelines?\n- Incremental verifiability: Can progress be measured at each step?\n\nWhen rejecting, classify your reasons using categories: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE.\n${prReviewModeAddendum()}`;\n}\n\n/** Build the architect role prompt. */\nfunction architectPrompt(project: string): string {\n return `You are a Software Architect voting on technical proposals for the ${project} project.\n\nYour evaluation criteria:\n- Technical design quality and architectural soundness\n- Scalability and performance implications\n- Maintainability and code organization\n- Alignment with existing patterns (Result<T,E>, Zod validation, TypeScript best practices)\n- Integration complexity with current codebase\n${voterFooter()}\n\nBe direct and technical. Focus on structural implications.`;\n}\n\n/** Build the security role prompt. */\nfunction securityPrompt(project: string): string {\n return `You are a Security Engineer voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- Security vulnerabilities and attack vectors (OWASP Top 10)\n- Input validation and sanitization\n- Secrets management and credential handling\n- Path traversal and injection prevention\n- Rate limiting and resource exhaustion\n${voterFooter()}\n\nBe thorough about risks. Flag any security concerns.`;\n}\n\n/** Build the devex role prompt. */\nfunction devexPrompt(project: string): string {\n return `You are a Developer Experience Engineer voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- API usability and ergonomics\n- Documentation clarity and completeness\n- Learning curve for new developers\n- Testing and debugging experience\n- CLI/tool integration quality\n${voterFooter()}\n\nFocus on practical developer impact.`;\n}\n\n/** Build the AI/ML role prompt. */\nfunction aiMlPrompt(project: string): string {\n return `You are an AI/ML Engineer voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- Multi-agent coordination effectiveness\n- Model selection and routing strategies\n- Context management and token efficiency\n- Learning and adaptation capabilities\n- Consensus protocol design\n- Integration with LLM capabilities\n${voterFooter()}\n\nEvaluate AI/ML implications and opportunities.`;\n}\n\n/** Build the PM role prompt. */\nfunction pmPrompt(project: string): string {\n return `You are a Product Manager voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- Business value and user impact\n- Resource requirements and timeline\n- Risk assessment and mitigation\n- Priority relative to roadmap\n- Success metrics and validation approach\n- Alignment with project goals in CLAUDE.md\n${voterFooter()}\n\nBalance value against effort. Be pragmatic.`;\n}\n\n/** Build the catfish (contrarian) role prompt. */\nfunction catfishPrompt(project: string): string {\n return `You are a Contrarian Analyst (catfish agent) voting on proposals for the ${project} project.\n\nYour role is to prevent false consensus by deliberately challenging proposals.\nBased on research (arXiv:2505.21503), agreement bias in multi-agent voting leads\nto poor decisions when agents rubber-stamp proposals without genuine scrutiny.\n\nYour evaluation criteria:\n- What are the hidden costs, risks, or downsides not mentioned?\n- What assumptions are being made that might be wrong?\n- What alternatives were not considered?\n- What could go wrong in practice vs. theory?\n- Is there scope creep or unnecessary complexity?\n\nWorkflow-test assessment (include in your reasoning):\n- Testability: Is the proposal verifiable, or just theoretical?\n- Workflow integration: Will this actually work in existing pipelines?\n- Incremental verifiability: Can we tell if it's working at each stage?\n\nWhen rejecting, you MUST classify your reasons using categories: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE.\n\nIMPORTANT: Your job is to find legitimate concerns, not to reject everything.\nIf after genuine scrutiny you find no significant issues, you MAY approve.\nBut your default posture is skeptical — look for what others might miss.\nHigh-confidence rejections with specific reasoning are your most valuable output.\n${prReviewModeAddendum()}`;\n}\n\n/**\n * Build the scope_steward role prompt (#2185).\n *\n * Different axis from `pm` (which prioritizes WHICH features to build) and\n * `catfish` (which doubts the framing). The steward asks: should we build\n * this AT ALL? Existing tools usually win; default bias is \"don't ship.\"\n */\nfunction scopeStewardPrompt(project: string): string {\n return `You are a Scope Steward voting on proposals for the ${project} project.\n\nYour job is to gate against build-when-buy-would-do and feature sprawl.\nThe originating case (2026-04-24): a 6-role panel approved building a USB flasher\nCLI without anyone flagging that Rufus already solves the problem better, for the\nsame audience, with 100M+ installs of battle-tested code. This role exists to\ncatch that class of mistake.\n\nYour evaluation criteria — work through these mandatory checks in your reasoning:\n\n1. **Existing-tool check.** Search your knowledge for tools, libraries, or\n services that already solve the stated problem. Name them concretely\n (not \"there might be alternatives\" — actual names: Rufus, ripgrep,\n esbuild, etc.). If you can't name an alternative, say so explicitly.\n\n2. **Build-vs-buy math.** For each existing tool you named: what would we\n LOSE by adopting it (license, dependency surface, integration cost)?\n What would we GAIN by building our own (tighter integration, no extra\n binary, etc.)? Default lean: BUY. Building is justified only when the\n loss column is concrete and the gain column is load-bearing.\n\n3. **Mission alignment.** Does this proposal serve the project's stated\n mission, or is it scope drift? If drift, name the drift specifically.\n\n4. **Kill-the-feature option.** For every proposal, explicitly evaluate\n \"what if we just didn't do this?\" as a ranked option. Many proposals\n don't need to be built. Make the no-build case before the build case.\n\n5. **Sprawl audit.** Check whether similar functionality already exists\n in the codebase. If it does, recommend extending — not forking. The\n anti-sprawl policy in CLAUDE.md is specifically the rule this role\n enforces.\n\nDefault bias: REJECT proposals where an existing tool fits, even if our\nown implementation would be marginally nicer. Only approve when the\nexisting-tool check fails AND the kill-the-feature option is worse AND\nmission alignment is clear AND no comparable in-codebase functionality\nexists.\n\nFew-shot example of a textbook rejection:\n> Proposal: \"Add an aegis-boot subcommand to flash bootable USB sticks.\"\n> Steward response: \"REJECT (DON'T-BUILD). Rufus has solved this for the\n> same audience for 10+ years with 100M+ installs and battle-tested code.\n> Adopting Rufus loses nothing material; building our own loses\n> maintenance bandwidth indefinitely. Mission alignment: aegis-boot's\n> mission is verifiable boot, not USB tooling. Kill option clearly wins.\n> No prior in-codebase functionality. Recommend: point users at Rufus in\n> the docs and stop here.\"\n\n${voterFooter()}\n\nWhen rejecting, you MUST classify reasons (YAGNI, DRY_VIOLATION,\nOVER_ENGINEERING, SCOPE_CREEP, MISALIGNED). The steward's most common\ncategories are SCOPE_CREEP, YAGNI, and OVER_ENGINEERING.\n\nYou CAN approve. But your default posture is: \"this should not be built;\nprove me wrong with the build-vs-buy math.\"`;\n}\n\nexport function getVoterPrompts(project: string = DEFAULT_PROJECT): Record<VoterRole, string> {\n return {\n architect: architectPrompt(project),\n security: securityPrompt(project),\n devex: devexPrompt(project),\n ai_ml: aiMlPrompt(project),\n pm: pmPrompt(project),\n catfish: catfishPrompt(project),\n scope_steward: scopeStewardPrompt(project),\n };\n}\n\n/**\n * Default prompts (backward compatible — uses 'nexus-agents' project context).\n */\nexport const VOTER_SYSTEM_PROMPTS: Record<VoterRole, string> = getVoterPrompts();\n\n/**\n * Base reasoning templates for simulated votes.\n *\n * scope_steward simulated reasoning intentionally reflects the role's\n * bias-toward-not-shipping posture (PM vote condition on #2185).\n */\nexport const SIMULATED_VOTE_REASONING: Record<VoterRole, string> = {\n architect: 'Evaluated technical design and architecture implications.',\n security: 'Reviewed security considerations and attack surface.',\n devex: 'Assessed developer experience and workflow impact.',\n ai_ml: 'Analyzed AI/ML capabilities and learning potential.',\n pm: 'Evaluated business value and resource requirements.',\n catfish: 'Challenged proposal assumptions and identified potential risks.',\n scope_steward:\n 'Checked existing tools, build-vs-buy math, kill-the-feature option; bias toward not shipping.',\n};\n","/**\n * nexus-agents voter response parsing\n *\n * Schema and parsing utilities for structured vote responses from LLM.\n *\n * (Source: Extracted from voter-agents.ts per Issue #285)\n */\n\nimport { z } from 'zod';\nimport type { Vote } from '../consensus/types.js';\nimport type { VoterRole } from './vote-types.js';\nimport { getErrorMessage, createLogger } from '../core/index.js';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\n/**\n * Error thrown when vote response parsing fails and synthetic votes not allowed.\n * (Source: Issue #512 - Fail-safe voting response parsing)\n *\n * By default, parseVoteResponse throws this error when JSON parsing or validation\n * fails. To use synthetic fallback votes (NOT RECOMMENDED), pass\n * `allowSyntheticVote: true` to the options parameter.\n */\nexport class SyntheticVoteError extends Error {\n constructor(\n reason: string,\n public readonly rawOutput: string\n ) {\n super(\n `Vote response parsing failed: ${reason}. ` +\n 'To use synthetic fallback votes (NOT RECOMMENDED), set allowSyntheticVote: true'\n );\n this.name = 'SyntheticVoteError';\n }\n}\n\n/**\n * Vote source tracking - indicates whether vote is real or synthetic.\n * (Source: Issue #512 - Voting integrity)\n */\nexport type ParsedVoteSource = 'parsed' | 'fallback';\n\n/**\n * Extended vote with source tracking.\n */\nexport interface ParsedVote extends Vote {\n readonly source: ParsedVoteSource;\n}\n\n/**\n * Options for parseVoteResponse.\n */\nexport interface ParseVoteOptions {\n /**\n * Allow synthetic fallback votes when parsing fails.\n * Default: false (throws SyntheticVoteError)\n * (Source: Issue #512 - Fail-safe voting)\n */\n readonly allowSyntheticVote?: boolean;\n}\n\n// ============================================================================\n// Structured Vote Response Schema\n// ============================================================================\n\n/**\n * Pre-verified finding shape — voter emits this; downstream\n * `isFindingVerified` adds the derived `verified` flag.\n *\n * #2245 follow-up: voters previously asked to embed YAML findings inside\n * the JSON `reasoning` field. That format is lossy across JSON\n * serialization (backticks/newlines). The v4 retest produced 0 findings\n * across 9 request_changes voters because the LLM either dropped the\n * YAML to keep JSON valid, or produced invalid JSON the parser rejected.\n * Solution: expose findings as a top-level array on the vote response.\n */\nexport const RawFindingSchema = z.object({\n summary: z.string().min(1).max(500).describe('One-line summary of the issue'),\n location: z.string().min(1).max(200).describe('path/file.ext:line'),\n severity: z.enum(['critical', 'high', 'medium', 'low']).default('medium'),\n gate: z.object({\n reread_cited_line: z.enum(['passed', 'failed', 'skipped']).default('skipped'),\n traced_call_path: z.enum(['passed', 'failed', 'skipped']).default('skipped'),\n named_assertion: z\n .string()\n .default('')\n .describe('Concrete failing assertion — substantive, not a rubber-stamp word'),\n ruled_out_language_non_issue: z.enum(['passed', 'failed', 'skipped']).default('skipped'),\n }),\n claim: z.string().min(1).max(2000).describe('What is wrong and why it justifies blocking'),\n});\n\nexport type RawFinding = z.infer<typeof RawFindingSchema>;\n\n/**\n * Zod schema for parsing structured vote responses from LLM.\n */\nexport const VoteResponseSchema = z.object({\n decision: z.enum(['approve', 'reject', 'abstain']).describe('Your vote decision'),\n reasoning: z.string().min(10).max(4000).describe('Explanation for your vote (10-4000 chars)'),\n confidence: z.number().min(0).max(1).describe('Confidence level 0-1'),\n conditions: z.array(z.string()).optional().describe('Optional conditions for approval'),\n /** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */\n rejectionCategories: z\n .array(\n z.enum([\n 'YAGNI',\n 'DRY_VIOLATION',\n 'OVER_ENGINEERING',\n 'SCOPE_CREEP',\n 'SECURITY_RISK',\n 'MISALIGNED',\n 'INSUFFICIENT_EVIDENCE',\n ])\n )\n .optional()\n .describe('Rejection reason categories when decision is reject'),\n /** Top-level structured findings for PR-review mode (#2245 v4 follow-up).\n * Replaces the YAML-in-reasoning encoding that proved lossy. */\n findings: z.array(RawFindingSchema).optional().describe('Structured findings (PR review only)'),\n});\n\nexport type VoteResponse = z.infer<typeof VoteResponseSchema>;\n\n/**\n * Hand-authored JSON Schema mirroring {@link VoteResponseSchema} (#3433).\n *\n * Used as the `input_schema` for a forced Claude `tool_use` call so the\n * ClaudeAdapter can honor `responseFormat: { type: 'json_schema' }` for votes.\n * `zod-to-json-schema` is intentionally NOT a dependency — this object is the\n * single source of truth for the JSON-Schema view of a vote response.\n *\n * Drift between this and `VoteResponseSchema` is caught by the contract test\n * in `voter-response.test.ts` (every Zod key must appear here and vice-versa).\n */\nexport const VOTE_JSON_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: false,\n required: ['decision', 'reasoning', 'confidence'],\n properties: {\n decision: {\n type: 'string',\n enum: ['approve', 'reject', 'abstain'],\n description: 'Your vote decision',\n },\n reasoning: {\n type: 'string',\n minLength: 10,\n maxLength: 4000,\n description: 'Explanation for your vote (10-4000 chars)',\n },\n confidence: {\n type: 'number',\n minimum: 0,\n maximum: 1,\n description: 'Confidence level 0-1',\n },\n conditions: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional conditions for approval',\n },\n rejectionCategories: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'YAGNI',\n 'DRY_VIOLATION',\n 'OVER_ENGINEERING',\n 'SCOPE_CREEP',\n 'SECURITY_RISK',\n 'MISALIGNED',\n 'INSUFFICIENT_EVIDENCE',\n ],\n },\n description: 'Rejection reason categories when decision is reject',\n },\n findings: {\n type: 'array',\n description: 'Structured findings (PR review only)',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['summary', 'location', 'severity', 'gate', 'claim'],\n properties: {\n summary: {\n type: 'string',\n minLength: 1,\n maxLength: 500,\n description: 'One-line summary of the issue',\n },\n location: {\n type: 'string',\n minLength: 1,\n maxLength: 200,\n description: 'path/file.ext:line',\n },\n severity: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] },\n gate: {\n type: 'object',\n additionalProperties: false,\n required: [\n 'reread_cited_line',\n 'traced_call_path',\n 'named_assertion',\n 'ruled_out_language_non_issue',\n ],\n properties: {\n reread_cited_line: { type: 'string', enum: ['passed', 'failed', 'skipped'] },\n traced_call_path: { type: 'string', enum: ['passed', 'failed', 'skipped'] },\n named_assertion: {\n type: 'string',\n description: 'Concrete failing assertion — substantive, not a rubber-stamp word',\n },\n ruled_out_language_non_issue: {\n type: 'string',\n enum: ['passed', 'failed', 'skipped'],\n },\n },\n },\n claim: {\n type: 'string',\n minLength: 1,\n maxLength: 2000,\n description: 'What is wrong and why it justifies blocking',\n },\n },\n },\n },\n },\n};\n\n// ============================================================================\n// Vote Prompt Construction\n// ============================================================================\n\n/** Example responses appended to vote prompts. Kept as a constant to keep\n * `buildVotePrompt` under the max-lines-per-function lint cap. */\nconst VOTE_PROMPT_EXAMPLES = `Example approve response:\n{\n \"decision\": \"approve\",\n \"reasoning\": \"The proposal aligns with architectural patterns. Testability: high — unit tests can verify each component. Workflow integration: fits existing CI pipeline.\",\n \"confidence\": 0.85,\n \"conditions\": [\"Add unit tests before merge\"]\n}\n\nExample reject response:\n{\n \"decision\": \"reject\",\n \"reasoning\": \"This adds speculative abstractions for hypothetical future needs. Testability: unclear — no concrete test plan provided.\",\n \"confidence\": 0.80,\n \"rejectionCategories\": [\"YAGNI\", \"OVER_ENGINEERING\"]\n}\n\nExample PR-review request_changes response with structured findings:\n{\n \"decision\": \"reject\",\n \"reasoning\": \"Off-by-one in clampPageSize and missing null guard on response.timing — both visible in the diff.\",\n \"confidence\": 0.9,\n \"rejectionCategories\": [\"INSUFFICIENT_EVIDENCE\"],\n \"findings\": [\n {\n \"summary\": \"Off-by-one in clampPageSize\",\n \"location\": \"packages/nexus-agents/src/api/pagination.ts:18\",\n \"severity\": \"high\",\n \"gate\": {\n \"reread_cited_line\": \"passed\",\n \"traced_call_path\": \"passed\",\n \"named_assertion\": \"Test would assert clampPageSize(50, 100) === 50; this returns 49.\",\n \"ruled_out_language_non_issue\": \"passed\"\n },\n \"claim\": \"Function name says 'clamp to range' but returns requested-1 in the in-range path.\"\n }\n ]\n}`;\n\n/**\n * Constructs the user prompt for vote evaluation.\n * Includes workflow-test evaluation criteria (Issue #1212) and\n * rejection category instructions (Issue #1213).\n */\nexport function buildVotePrompt(proposal: string): string {\n return `Evaluate the following proposal and provide your vote.\n\nPROPOSAL:\n${proposal}\n\nIn addition to your role-specific criteria, assess these workflow-test dimensions:\n- Testability: Can the proposed changes be verified with automated tests?\n- Workflow integration: Does this fit into existing CI/make/test workflows?\n- Incremental verifiability: Can progress be measured at each step?\n\nRespond with a JSON object containing:\n- decision: \"approve\", \"reject\", or \"abstain\"\n- reasoning: Explanation for your vote (10-4000 characters). Include your workflow-test assessment.\n- confidence: Number between 0 and 1\n- conditions: Optional array of conditions for approval\n- rejectionCategories: Required when rejecting. Array of categories from: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE\n- findings: PR-REVIEW MODE ONLY. Optional top-level array of structured findings — see \"PR-review mode\" in the system prompt. OMIT this field entirely when reviewing a non-diff proposal or when approving a diff.\n\n${VOTE_PROMPT_EXAMPLES}`;\n}\n\n// ============================================================================\n// Vote Response Parsing\n// ============================================================================\n\n/**\n * Extracts JSON from LLM response text.\n * Handles responses that may include markdown code blocks.\n */\nexport function extractJsonFromResponse(text: string): string {\n // Try to find JSON in code blocks first\n const codeBlockMatch = /```(?:json)?\\s*([\\s\\S]*?)```/i.exec(text);\n if (codeBlockMatch?.[1] !== undefined) {\n return codeBlockMatch[1].trim();\n }\n\n // Look for JSON object directly\n const jsonMatch = /\\{[\\s\\S]*\\}/i.exec(text);\n if (jsonMatch?.[0] !== undefined) {\n return jsonMatch[0];\n }\n\n return text.trim();\n}\n\n/**\n * Creates a fallback vote when parsing fails.\n * Attempts to infer decision from text content.\n * ONLY used when allowSyntheticVote is explicitly true.\n * (Source: Issue #512 - Fail-safe voting)\n */\nfunction createFallbackVote(output: string, _role: VoterRole, reason: string): ParsedVote {\n const lower = output.toLowerCase();\n let decision: Vote['decision'] = 'abstain';\n\n // Simple keyword detection - heuristic only\n // Check reject keywords FIRST since \"disagree\" contains \"agree\" substring\n if (lower.includes('reject') || lower.includes('decline') || lower.includes('disagree')) {\n decision = 'reject';\n } else if (lower.includes('approve') || lower.includes('accept') || lower.includes('agree')) {\n decision = 'approve';\n }\n\n // Log warning about synthetic vote\n createLogger({ component: 'voter-response' }).warn(\n 'Creating synthetic vote (NOT parsed from LLM output)',\n { decision, reason }\n );\n\n return {\n decision,\n reasoning: `[SYNTHETIC: ${reason}] ${output.slice(0, 200)}`,\n confidence: 0.5,\n source: 'fallback', // Mark as synthetic\n };\n}\n\n/** Maps a validated VoteResponse into a ParsedVote, threading optional fields. */\nfunction buildParsedVote(data: VoteResponse): ParsedVote {\n return {\n decision: data.decision,\n reasoning: data.reasoning,\n confidence: data.confidence,\n ...(data.conditions !== undefined ? { conditions: data.conditions } : {}),\n ...(data.rejectionCategories !== undefined\n ? { rejectionCategories: data.rejectionCategories }\n : {}),\n ...(data.findings !== undefined ? { findings: data.findings } : {}),\n source: 'parsed',\n };\n}\n\n/**\n * Parses vote response from LLM output.\n *\n * By default, throws SyntheticVoteError if parsing fails. To use synthetic\n * fallback votes (NOT RECOMMENDED), pass `allowSyntheticVote: true`.\n *\n * (Source: Issue #512 - Fail-safe voting response parsing)\n *\n * @param output - Raw LLM output text\n * @param role - Voter role for context\n * @param options - Parsing options including allowSyntheticVote\n * @returns ParsedVote with source tracking\n * @throws SyntheticVoteError if parsing fails and allowSyntheticVote is false\n */\nexport function parseVoteResponse(\n output: string,\n role: VoterRole,\n options?: ParseVoteOptions\n): ParsedVote {\n const allowSyntheticVote = options?.allowSyntheticVote ?? false;\n\n try {\n const jsonStr = extractJsonFromResponse(output);\n const parsed = JSON.parse(jsonStr) as unknown;\n const validated = VoteResponseSchema.safeParse(parsed);\n\n if (validated.success) {\n return buildParsedVote(validated.data);\n }\n\n // Validation failed - throw or fallback based on config\n const reason = `Validation failed: ${validated.error.issues.map((e: { message: string }) => e.message).join(', ')}`;\n if (!allowSyntheticVote) {\n throw new SyntheticVoteError(reason, output);\n }\n return createFallbackVote(output, role, reason);\n } catch (error) {\n // If it's already a SyntheticVoteError, rethrow it\n if (error instanceof SyntheticVoteError) {\n throw error;\n }\n\n // Parse error - throw or fallback based on config\n const reason = getErrorMessage(error, 'Unknown parse error');\n if (!allowSyntheticVote) {\n throw new SyntheticVoteError(reason, output);\n }\n return createFallbackVote(output, role, reason);\n }\n}\n","/**\n * nexus-agents voter execution utilities\n *\n * Vote execution helpers including result creation, timeout handling,\n * retry logic, and simulation fallback.\n *\n * (Source: Extracted from voter-agents.ts per Issue #285)\n */\n\nimport type { Vote } from '../consensus/types.js';\nimport type { VoterRole, AgentVoteResult } from './vote-types.js';\nimport type { IModelAdapter, CompletionRequest, ILogger } from '../core/index.js';\nimport { getRandomProvider } from '../core/index.js';\nimport { delay, withTimeout } from '../utils/async-utils.js';\nimport { VOTER_SYSTEM_PROMPTS, SIMULATED_VOTE_REASONING } from './voter-prompts.js';\nimport {\n buildVotePrompt,\n parseVoteResponse,\n SyntheticVoteError,\n VOTE_JSON_SCHEMA,\n} from './voter-response.js';\n\n// Import timeout constants from canonical source (Issue #984)\nimport {\n VOTE_TIMEOUTS,\n resolveVoteTimeout as _resolveVoteTimeout,\n validateTimeout as _validateTimeout,\n} from '../config/timeouts.js';\n\n/** Default vote timeout. Canonical source: `config/timeouts.ts`. */\nexport const DEFAULT_VOTE_TIMEOUT_MS = VOTE_TIMEOUTS.defaultMs;\n\n/** Resolves vote timeout with env var override. Canonical: `config/timeouts.ts`. */\nexport const resolveVoteTimeout = _resolveVoteTimeout;\n\n/** Maximum vote timeout. Canonical source: `config/timeouts.ts`. */\nexport const MAX_VOTE_TIMEOUT_MS = VOTE_TIMEOUTS.maxMs;\n\n/** Minimum vote timeout. Canonical source: `config/timeouts.ts`. */\nexport const MIN_VOTE_TIMEOUT_MS = VOTE_TIMEOUTS.minMs;\n\n/** Maximum retries per vote. Canonical source: `config/timeouts.ts`. */\nexport const DEFAULT_MAX_RETRIES = VOTE_TIMEOUTS.maxRetries;\n\n/**\n * Initial retry delay in milliseconds.\n */\nconst INITIAL_RETRY_DELAY_MS = 1_000;\n\n/**\n * Retry delay for rate-limit errors in milliseconds (Issue #1319).\n * Longer than standard to respect API rate limits.\n */\nexport const RATE_LIMIT_RETRY_DELAY_MS = 5_000;\n\n/**\n * Detects whether an error message indicates a rate-limit condition.\n * Delegates to canonical rate-limit-detector (DRY consolidation Issue #1596).\n */\nimport { isRateLimitLikeError } from '../adapters/rate-limit-detector.js';\n\n/** @see isRateLimitLikeError — re-exported for backward compatibility */\nexport function isRateLimitError(message: string): boolean {\n return isRateLimitLikeError(new Error(message));\n}\n\n/**\n * Validates and clamps timeout to `[VOTE_TIMEOUTS.minMs, VOTE_TIMEOUTS.maxMs]`.\n *\n * **Canonical source:** `config/timeouts.ts`. This re-export exists for\n * back-compat — new code should import from `../config/timeouts.js`\n * directly (#2637).\n */\nexport const validateTimeout = _validateTimeout;\n\n// ============================================================================\n// Vote Result Helpers\n// ============================================================================\n\n/**\n * Creates an error vote result (abstain with error message).\n * Issue #523: Uses source: 'error' instead of 'llm' for accuracy.\n */\nexport function createErrorVoteResult(\n role: VoterRole,\n errorMsg: string,\n processingTimeMs: number\n): AgentVoteResult {\n return {\n role,\n vote: {\n decision: 'abstain',\n reasoning: `[Error] Vote execution failed: ${errorMsg}`,\n confidence: 0,\n },\n processingTimeMs,\n source: 'error',\n error: errorMsg,\n };\n}\n\n/**\n * Creates a simulation vote result.\n */\nexport function createSimulationVoteResult(\n role: VoterRole,\n proposal: string,\n processingTimeMs: number,\n error?: string\n): AgentVoteResult {\n return {\n role,\n vote: simulateVote(role, proposal),\n processingTimeMs,\n source: 'simulation',\n ...(error !== undefined && { error }),\n };\n}\n\n/**\n * Creates simulated votes for multiple roles.\n */\nexport function createSimulatedVotes(\n roles: readonly VoterRole[],\n proposal: string,\n error?: string\n): readonly AgentVoteResult[] {\n const random = getRandomProvider();\n return roles.map((role) =>\n createSimulationVoteResult(role, proposal, random.randomInt(0, 100), error)\n );\n}\n\n/**\n * Role-specific vote distributions for simulation.\n * Each role has weighted probabilities reflecting their typical concerns:\n * - security: More skeptical, finds potential issues\n * - architect: Technically focused, generally supportive of good design\n * - devex: Balanced, considers usability\n * - ai_ml: Technically focused, evaluates AI aspects\n * - pm: Business focused, generally supportive of value\n *\n * Format: [approve_weight, reject_weight, abstain_weight]\n */\nconst ROLE_VOTE_DISTRIBUTIONS: Record<VoterRole, [number, number, number]> = {\n security: [40, 45, 15], // More skeptical - security concerns\n architect: [55, 30, 15], // Generally approving of good design\n devex: [50, 30, 20], // Balanced - considers usability\n ai_ml: [55, 30, 15], // Technical focus\n pm: [55, 25, 20], // Business focus - generally supportive\n catfish: [20, 65, 15], // Deliberately contrarian - challenges proposals (arXiv:2505.21503)\n scope_steward: [25, 60, 15], // Default-bias toward not shipping (#2185)\n};\n\n/**\n * Selects a decision based on weighted probabilities.\n */\nfunction selectWeightedDecision(\n weights: [number, number, number]\n): 'approve' | 'reject' | 'abstain' {\n const random = getRandomProvider();\n const total = weights[0] + weights[1] + weights[2];\n const rand = random.random() * total;\n\n if (rand < weights[0]) return 'approve';\n if (rand < weights[0] + weights[1]) return 'reject';\n return 'abstain';\n}\n\n/**\n * Fallback simulation when LLM is unavailable.\n * Uses role-specific vote distributions to provide more realistic simulation.\n * Clearly marks output as simulated.\n *\n * (Improved per Issue #453 - remove hardcoded 60% approve bias)\n */\nexport function simulateVote(role: VoterRole, proposal: string): Vote {\n const random = getRandomProvider();\n const weights = ROLE_VOTE_DISTRIBUTIONS[role];\n const decision = selectWeightedDecision(weights);\n\n // Confidence varies by decision type and role\n // Rejections tend to be higher confidence (found specific issue)\n // Approvals are moderate confidence (no issues found, but limited analysis)\n // Abstains are low confidence (insufficient information)\n let baseConfidence: number;\n if (decision === 'reject') {\n baseConfidence = 0.6 + random.random() * 0.3; // 0.6-0.9\n } else if (decision === 'approve') {\n baseConfidence = 0.5 + random.random() * 0.3; // 0.5-0.8\n } else {\n baseConfidence = 0.3 + random.random() * 0.2; // 0.3-0.5\n }\n\n return {\n decision,\n reasoning: `[Simulated - no LLM available] ${SIMULATED_VOTE_REASONING[role]} Proposal: \"${proposal.slice(0, 50)}...\"`,\n confidence: baseConfidence,\n };\n}\n\n// ============================================================================\n// Timeout and Retry Utilities\n// ============================================================================\n\n// Re-export from canonical source for backward compatibility\nexport { withTimeout, delay } from '../utils/async-utils.js';\n\n// ============================================================================\n// Vote Attempt Execution\n// ============================================================================\n\n/**\n * Extracts text content from completion response.\n */\nexport function extractTextFromResponse(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .map((block) => {\n if (typeof block === 'object' && block !== null && 'type' in block) {\n const typed = block as { type: string; text?: string };\n if (typed.type === 'text' && typeof typed.text === 'string') {\n return typed.text;\n }\n }\n return '';\n })\n .join('');\n }\n return String(content);\n}\n\n/**\n * Executes a single vote attempt (no retries).\n *\n * By default, throws SyntheticVoteError if response parsing fails.\n * This ensures we only get real LLM votes, not synthetic fallbacks.\n * (Source: Issue #512 - Fail-safe voting)\n */\n/**\n * Builds the vote completion request. `withResponseFormat` toggles the native\n * structured-output ask (#3433): on for the first attempt, off for the #3497\n * retry against backends that route `json_schema` through provider tool-use.\n * The `parseVoteResponse` regex/Zod path below accepts prose-wrapped JSON, so\n * omitting `responseFormat` is safe — it just loses the schema-enforced shape.\n */\nfunction buildVoteRequest(\n role: VoterRole,\n proposal: string,\n timeoutMs: number,\n withResponseFormat: boolean\n): CompletionRequest {\n const base: CompletionRequest = {\n messages: [\n { role: 'system', content: VOTER_SYSTEM_PROMPTS[role] },\n { role: 'user', content: buildVotePrompt(proposal) },\n ],\n // 2000 (#2245): JSON envelope + reasoning + YAML findings exceed the old 500.\n maxTokens: 2000,\n temperature: 0.3, // Low temperature for consistent evaluations\n // Thread the vote budget so the CLI timeout doesn't fire first (#3304); pass\n // signal too for CLI-vs-API cancellation parity (#3036/#3304).\n timeoutMs,\n signal: AbortSignal.timeout(timeoutMs),\n };\n return withResponseFormat\n ? { ...base, responseFormat: { type: 'json_schema', schema: VOTE_JSON_SCHEMA } }\n : base;\n}\n\n/**\n * #3497: some backends don't silently ignore an unsupported `responseFormat`.\n * OpenRouter implements `json_schema` via provider tool-use, so a role routed to\n * a provider without tool-use returns a hard 404 \"No endpoints found that\n * support tool use\" instead of ignoring the field — silently shrinking the panel\n * (observed on devex/catfish). Detect it so the caller retries without it.\n */\nfunction isStructuredOutputUnsupported(errorMessage: string): boolean {\n return /support tool use/i.test(errorMessage);\n}\n\n/** One completion attempt: build → complete (timeout-bounded) → extract text. */\nasync function runVoteCompletion(\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n timeoutMs: number,\n withResponseFormat: boolean\n): Promise<{ ok: true; output: string } | { ok: false; error: string }> {\n const request = buildVoteRequest(role, proposal, timeoutMs, withResponseFormat);\n const timeoutResult = await withTimeout(\n adapter.complete(request),\n timeoutMs,\n `Vote timeout after ${String(timeoutMs)}ms for role: ${role}`\n );\n if (!timeoutResult.ok) return { ok: false, error: timeoutResult.error };\n const response = timeoutResult.value;\n if (!response.ok) return { ok: false, error: response.error.message };\n return { ok: true, output: extractTextFromResponse(response.value.content) };\n}\n\nexport async function executeSingleVoteAttempt(\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n timeoutMs: number\n): Promise<{ ok: true; vote: Vote; output: string } | { ok: false; error: string }> {\n let completion = await runVoteCompletion(role, proposal, adapter, timeoutMs, true);\n // #3497: retry once WITHOUT responseFormat when the backend rejects the\n // tool-use-backed structured-output ask, so the panel keeps full strength.\n if (!completion.ok && isStructuredOutputUnsupported(completion.error)) {\n completion = await runVoteCompletion(role, proposal, adapter, timeoutMs, false);\n }\n if (!completion.ok) return { ok: false, error: completion.error };\n\n try {\n // parseVoteResponse throws SyntheticVoteError if parsing fails — we only\n // accept real LLM votes, not synthetic fallbacks.\n const vote = parseVoteResponse(completion.output, role);\n return { ok: true, vote, output: completion.output };\n } catch (error) {\n if (error instanceof SyntheticVoteError) {\n return { ok: false, error: `Vote parsing failed: ${error.message}` };\n }\n throw error; // Re-throw unexpected errors\n }\n}\n\n/** Options for executeWithRetries. */\nexport interface RetryOptions {\n readonly role: VoterRole;\n readonly proposal: string;\n readonly adapter: IModelAdapter;\n readonly logger: ILogger;\n readonly timeoutMs: number;\n readonly maxRetries: number;\n}\n\n/**\n * Executes vote attempts with retry logic.\n * Returns the error message from last failed attempt, or undefined if successful.\n */\nexport async function executeWithRetries(\n opts: RetryOptions\n): Promise<{ vote: Vote; ok: true } | { error: string; ok: false }> {\n const { role, proposal, adapter, logger, timeoutMs, maxRetries } = opts;\n let lastError = '';\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (attempt > 0) {\n const isRateLimit = isRateLimitError(lastError);\n const baseDelay = isRateLimit ? RATE_LIMIT_RETRY_DELAY_MS : INITIAL_RETRY_DELAY_MS;\n const delayMs = baseDelay * Math.pow(2, attempt - 1);\n logger.debug('Retrying vote execution', { role, attempt, delayMs, isRateLimit });\n await delay(delayMs);\n }\n\n // #2472: per-attempt timing breakdown so investigators can see which\n // retry succeeded (or which attempt blew the cap). Total vote time\n // is already captured at the call-site; this fills the per-attempt gap.\n const attemptStart = Date.now();\n const result = await executeSingleVoteAttempt(role, proposal, adapter, timeoutMs);\n const attemptMs = Date.now() - attemptStart;\n if (result.ok) {\n logger.info('Vote attempt timing', {\n role,\n attempt: attempt + 1,\n attemptMs,\n succeeded: true,\n });\n return { vote: result.vote, ok: true };\n }\n\n lastError = result.error;\n const rateLimited = isRateLimitError(lastError);\n logger.info('Vote attempt timing', {\n role,\n attempt: attempt + 1,\n attemptMs,\n succeeded: false,\n rateLimited,\n });\n logger.warn('Vote attempt failed', {\n role,\n attempt: attempt + 1,\n maxRetries: maxRetries + 1,\n error: lastError,\n ...(rateLimited ? { rateLimited: true } : {}),\n });\n }\n\n return { error: lastError !== '' ? lastError : 'Unknown error after all retries', ok: false };\n}\n","/**\n * Overall-deadline racing for consensus voting (Issue #1871).\n *\n * Defensive layer above per-vote timeouts: even if a single\n * executeAgentVote() promise never settles (subprocess adapter hang,\n * IPC wait that swallows timeout, etc.), this helper guarantees the\n * whole consensus call returns bounded partial results.\n *\n * Each role's vote promise is raced against a shared wall-clock\n * deadline. Any role whose promise has not settled when the deadline\n * fires is filled with createErrorVoteResult('overall consensus\n * deadline exceeded'), preserving role order so downstream aggregation\n * stays deterministic.\n */\nimport type { IModelAdapter, ILogger } from '../core/index.js';\nimport type { AgentVoteResult, VoterRole } from './vote-types.js';\nimport { createErrorVoteResult, delay } from './voter-execution.js';\n\nexport interface VoteOptions {\n readonly timeoutMs: number;\n readonly maxRetries: number;\n readonly allowSimulation: boolean;\n}\n\nexport type VoteFn = (\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n logger: ILogger,\n options: VoteOptions\n) => Promise<AgentVoteResult>;\n\nexport interface LaunchVotesInput {\n readonly roles: readonly VoterRole[];\n readonly proposal: string;\n readonly roleAdapters: ReadonlyMap<VoterRole, IModelAdapter>;\n readonly fallbackAdapter: IModelAdapter;\n readonly logger: ILogger;\n readonly voteOptions: VoteOptions;\n readonly interDelay: number;\n readonly overallDeadlineMs: number;\n /** Vote launcher (injected by caller — typically executeAgentVote). */\n readonly voteFn: VoteFn;\n}\n\nconst DEADLINE_MESSAGE = 'overall consensus deadline exceeded';\n\n/**\n * Should a failed vote be retried on the fallback adapter? Only when the diverse\n * adapter produced a genuine error (not the overall-deadline filler, which means\n * there's no time left) AND it wasn't already the fallback (#3587).\n */\nfunction shouldRetryOnFallback(\n result: AgentVoteResult,\n used: IModelAdapter,\n fallback: IModelAdapter\n): boolean {\n return (\n result.source === 'error' &&\n result.error !== DEADLINE_MESSAGE &&\n adapterCliKey(used) !== adapterCliKey(fallback)\n );\n}\n\n/** Stable per-CLI key for an adapter; CLI adapters carry the CLI name. */\nfunction adapterCliKey(adapter: IModelAdapter): string {\n return (adapter as { name?: string }).name ?? adapter.providerId;\n}\n\n/**\n * Per-key serializer (#3348). Returns a `run(key, fn)` that chains each fn\n * behind the previous fn for the same key, so at most one runs per key at a\n * time. Different keys run concurrently.\n *\n * Why: when several voter roles round-robin onto the SAME CLI, concurrent\n * subprocesses each trigger that CLI's OAuth access-token refresh. With\n * refresh-token rotation the first call rotates the token and the rest fail\n * with \"refresh token already used\". Serializing per CLI lets the cold-start\n * refresh complete before the next same-CLI call begins. Cross-CLI parallelism\n * is preserved (claude/gemini/codex still overlap).\n */\nfunction createKeyedSerializer(): <T>(key: string, fn: () => Promise<T>) => Promise<T> {\n const tails = new Map<string, Promise<unknown>>();\n return <T>(key: string, fn: () => Promise<T>): Promise<T> => {\n const prev = tails.get(key) ?? Promise.resolve();\n // Run fn whether the previous same-key call resolved or rejected.\n const run = prev.then(fn, fn);\n // Chain on a never-rejecting tail so one failure can't break ordering.\n tails.set(\n key,\n run.then(\n () => undefined,\n () => undefined\n )\n );\n return run;\n };\n}\n\nfunction raceWithDeadline(\n p: Promise<AgentVoteResult>,\n role: VoterRole,\n deadlineMs: number\n): Promise<AgentVoteResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeoutP = new Promise<AgentVoteResult>((resolve) => {\n timer = setTimeout(() => {\n resolve(createErrorVoteResult(role, DEADLINE_MESSAGE, deadlineMs));\n }, deadlineMs);\n });\n return Promise.race([p, timeoutP]).finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n}\n\nexport async function launchVotesWithOverallDeadline(\n input: LaunchVotesInput\n): Promise<readonly AgentVoteResult[]> {\n const {\n roles,\n proposal,\n roleAdapters,\n fallbackAdapter,\n logger,\n voteOptions,\n interDelay,\n overallDeadlineMs,\n voteFn,\n } = input;\n\n const startedAt = Date.now();\n const serialize = createKeyedSerializer();\n\n // One serialized, deadline-bounded vote attempt on a specific adapter.\n const voteOnAdapter = (role: VoterRole, adapter: IModelAdapter): Promise<AgentVoteResult> =>\n // Serialize per CLI so concurrent same-CLI calls don't race that CLI's\n // OAuth refresh (#3348). The deadline is measured when the vote actually\n // starts, so a queued role still gets a correct remaining budget.\n serialize(adapterCliKey(adapter), () => {\n const remaining = Math.max(1, overallDeadlineMs - (Date.now() - startedAt));\n return raceWithDeadline(\n voteFn(role, proposal, adapter, logger, voteOptions),\n role,\n remaining\n );\n });\n\n const wrapped = roles.map(async (role, i): Promise<AgentVoteResult> => {\n if (i > 0 && interDelay > 0) await delay(interDelay);\n const adapter = roleAdapters.get(role) ?? fallbackAdapter;\n const primary = await voteOnAdapter(role, adapter);\n // #3587: a voter routed to a diverse CLI that hard-fails (e.g. an OpenRouter\n // model without tool-use → \"no endpoints that support tool use\", which the\n // responseFormat retry can't fix) would silently shrink the panel. Retry\n // once on the known-good fallback adapter so one bad CLI can't drop a voter.\n if (!shouldRetryOnFallback(primary, adapter, fallbackAdapter)) return primary;\n logger.warn('Voter failed on diverse adapter; retrying on fallback (#3587)', {\n role,\n failedCli: adapterCliKey(adapter),\n fallbackCli: adapterCliKey(fallbackAdapter),\n error: primary.error,\n });\n return voteOnAdapter(role, fallbackAdapter);\n });\n\n const results = await Promise.all(wrapped);\n\n const expired = results.filter((r) => r.source === 'error' && r.error === DEADLINE_MESSAGE);\n if (expired.length > 0) {\n logger.warn('Consensus overall deadline reached; returning partial results', {\n totalRoles: roles.length,\n expiredRoles: expired.map((r) => r.role),\n overallDeadlineMs,\n });\n }\n return results;\n}\n","/**\n * nexus-agents voter agents\n *\n * Real LLM-powered voter agents for consensus voting.\n * Replaces simulated voting with actual agent execution that\n * analyzes proposals.\n *\n * (Source: Issue #226, Sprint #229)\n * (Updated: Issue #280 - Fixed timeout handling, removed simulation fallback)\n * (Refactored: Issue #285 - Extracted response and execution utilities)\n *\n * File structure:\n * - voter-prompts.ts: System prompts for each voter role\n * - voter-response.ts: Response parsing and validation\n * - voter-execution.ts: Execution utilities (timeout, retry, result creation)\n * - voter-agents.ts: Main API (this file)\n */\n\nimport type { VoterRole, AgentVoteResult } from './vote-types.js';\nimport { VOTER_ROLES } from './vote-types.js';\nimport type { IModelAdapter, ILogger } from '../core/index.js';\nimport { createLogger, getTimeProvider, getErrorMessage } from '../core/index.js';\nimport { getGlobalRegistry } from '../adapters/unified-registry.js';\nimport { getAvailableClis } from '../cli-adapters/factory.js';\nimport { authRemediation } from '../cli-adapters/cli-error-envelope.js';\nimport type { CliName } from '../cli-adapters/types.js';\nimport { checkCodexConcurrency } from '../cli-adapters/codex-limits.js';\n\n// Re-export prompts for backward compatibility\nexport { VOTER_SYSTEM_PROMPTS, SIMULATED_VOTE_REASONING } from './voter-prompts.js';\n\n// Re-export response utilities for backward compatibility\nexport {\n VoteResponseSchema,\n type VoteResponse,\n buildVotePrompt,\n extractJsonFromResponse,\n parseVoteResponse,\n SyntheticVoteError,\n type ParsedVote,\n type ParsedVoteSource,\n type ParseVoteOptions,\n} from './voter-response.js';\n\n// Re-export execution utilities for backward compatibility\nexport {\n DEFAULT_VOTE_TIMEOUT_MS,\n MAX_VOTE_TIMEOUT_MS,\n MIN_VOTE_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n RATE_LIMIT_RETRY_DELAY_MS,\n createErrorVoteResult,\n createSimulationVoteResult,\n createSimulatedVotes,\n simulateVote,\n isRateLimitError,\n withTimeout,\n delay,\n extractTextFromResponse,\n executeSingleVoteAttempt,\n resolveVoteTimeout,\n type RetryOptions,\n executeWithRetries,\n} from './voter-execution.js';\n\n// Import from execution module for internal use\nimport {\n createErrorVoteResult,\n createSimulationVoteResult,\n createSimulatedVotes,\n executeWithRetries,\n} from './voter-execution.js';\nimport { resolveVoteTimeout, VOTE_TIMEOUTS, getMcpSafeDeadlineMs } from '../config/timeouts.js';\nimport { launchVotesWithOverallDeadline } from './voter-agents-deadline.js';\n\n/**\n * Computes an overall wall-clock deadline for a consensus vote call (#1871).\n *\n * Acts as a safety net above per-vote timeouts: even if executeAgentVote's\n * internal withTimeout race fails to resolve (e.g. subprocess adapter hang),\n * this deadline bounds total wall time and lets partial results return.\n *\n * Formula: worst-case legitimate completion (timeoutMs * (maxRetries+1))\n * plus staggered launch headroom, plus `VOTE_TIMEOUTS.overallDeadlineBufferMs`.\n */\nexport function computeOverallConsensusDeadlineMs(\n timeoutMs: number,\n maxRetries: number,\n roleCount: number,\n interDelayMs: number\n): number {\n const perVoteBudget = timeoutMs * (maxRetries + 1);\n const staggerBudget = Math.max(0, roleCount - 1) * interDelayMs;\n return perVoteBudget + staggerBudget + VOTE_TIMEOUTS.overallDeadlineBufferMs;\n}\n\n// ============================================================================\n// Agent Vote Execution\n// ============================================================================\n\n/**\n * Options for executing voter agents.\n */\n/** Default inter-agent delay to prevent rate limiting (ms). Raised from 1s to 2s (#1802). */\nexport const DEFAULT_INTER_AGENT_DELAY_MS = 2000;\n\nexport interface VoterAgentOptions {\n /** Logger instance */\n readonly logger?: ILogger;\n /** Model adapter to use (auto-selected if not provided) */\n readonly adapter?: IModelAdapter;\n /** Timeout per vote in milliseconds (default: 120000, override via NEXUS_VOTE_TIMEOUT_MS) */\n readonly timeoutMs?: number;\n /** Maximum retries per vote (default: 2) */\n readonly maxRetries?: number;\n /** Whether to allow simulation fallback (default: false per Issue #280) */\n readonly allowSimulation?: boolean;\n /** Delay between launching each agent vote to prevent rate limiting (default: 1000ms). Set to 0 to disable. */\n readonly interAgentDelayMs?: number;\n}\n\n// Re-export AgentVoteResult for convenience\nexport type { AgentVoteResult };\n\nconst defaultLogger = createLogger({ component: 'voter-agents' });\n\n/**\n * Executes a real LLM vote for a single role with timeout and retry support.\n *\n * Per Issue #280: No simulation fallback by default. Returns error result\n * instead of simulated vote when execution fails.\n */\nexport async function executeAgentVote(\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n logger: ILogger,\n options?: { timeoutMs?: number; maxRetries?: number; allowSimulation?: boolean }\n): Promise<AgentVoteResult> {\n const start = getTimeProvider().now();\n const timeoutMs = options?.timeoutMs ?? resolveVoteTimeout();\n const maxRetries = options?.maxRetries ?? VOTE_TIMEOUTS.maxRetries;\n const allowSimulation = options?.allowSimulation ?? false;\n\n logger.info('Executing vote', { role, model: adapter.modelId, provider: adapter.providerId });\n\n const result = await executeWithRetries({\n role,\n proposal,\n adapter,\n logger,\n timeoutMs,\n maxRetries,\n });\n const processingTimeMs = getTimeProvider().now() - start;\n\n if (result.ok) {\n logger.info('Vote completed', { role, model: adapter.modelId, decision: result.vote.decision });\n return { role, vote: result.vote, processingTimeMs, source: 'llm', cli: adapter.providerId };\n }\n\n // All retries exhausted\n logger.error('Vote execution failed after all retries', undefined, {\n role,\n model: adapter.modelId,\n errorMessage: result.error,\n });\n\n if (allowSimulation) {\n logger.warn('Falling back to simulation (allowSimulation=true)', { role });\n return createSimulationVoteResult(role, proposal, processingTimeMs, result.error);\n }\n\n // #3350: a stale-OAuth failure (e.g. codex \"refresh token already used\")\n // surfaces here as a raw fail-closed error with no operator signal. Append a\n // one-line `<cli> login` remediation when the error is an auth error. Vote\n // semantics are unchanged — this is still an error (abstain) vote.\n const remediation = authRemediation(result.error, adapter.providerId);\n const errorText = remediation === null ? result.error : `${result.error}\\n\\n${remediation}`;\n return createErrorVoteResult(role, errorText, processingTimeMs);\n}\n\n// ============================================================================\n// Batch Vote Collection\n// ============================================================================\n\n/**\n * Options for collecting votes from multiple agents.\n */\nexport interface CollectRealVotesOptions extends VoterAgentOptions {\n /** Voter roles to include */\n readonly roles: readonly VoterRole[];\n /** Proposal text */\n readonly proposal: string;\n /** Use simulation mode (explicit opt-in only) */\n readonly simulate?: boolean;\n}\n\n/**\n * Error thrown when no adapter is available and simulation is disabled.\n */\nexport class NoAdapterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NoAdapterError';\n }\n}\n\n/**\n * Resolves the model adapter, handling errors per Issue #280.\n */\nfunction resolveAdapter(\n options: CollectRealVotesOptions,\n logger: ILogger\n): { adapter: IModelAdapter } | { error: string } {\n try {\n if (options.adapter !== undefined) return { adapter: options.adapter };\n const registry = getGlobalRegistry({ logger });\n return { adapter: registry.getDefault() };\n } catch (error) {\n return { error: getErrorMessage(error) };\n }\n}\n\n/**\n * #2659 — warn (don't block) when more voter roles land on Codex than its\n * default `max_threads`, e.g. a single-CLI fallback with a full panel.\n */\nfunction warnIfCodexConcurrencyExceeded(\n roleAdapters: ReadonlyMap<VoterRole, IModelAdapter>,\n logger: ILogger\n): void {\n const codexBound = [...roleAdapters.values()].filter(\n (a) => (a as { name?: string }).name === 'codex'\n ).length;\n const warning = checkCodexConcurrency(codexBound);\n if (warning !== null) {\n logger.warn('Codex concurrency limit may be exceeded', { detail: warning });\n }\n}\n\n/** Assigns a single adapter to all roles (fallback path). */\nfunction assignUniformAdapter(\n roles: readonly VoterRole[],\n adapter: IModelAdapter\n): Map<VoterRole, IModelAdapter> {\n const adapters = new Map<VoterRole, IModelAdapter>();\n for (const role of roles) adapters.set(role, adapter);\n return adapters;\n}\n\n/** Creates CLI-specific adapters for available CLIs via the unified registry. */\nfunction createCliAdapterMap(\n clis: readonly CliName[],\n logger: ILogger\n): Map<CliName, IModelAdapter> {\n const registry = getGlobalRegistry({ logger });\n const result = new Map<CliName, IModelAdapter>();\n for (const cli of clis) {\n result.set(cli, registry.getAdapterForCli(cli));\n }\n return result;\n}\n\n/**\n * Creates diverse per-role adapters using all available CLIs (Issue #845).\n * Distributes roles across CLIs in round-robin fashion for model diversity.\n * Falls back to single adapter if only one CLI is available.\n */\nasync function resolveDiverseAdapters(\n roles: readonly VoterRole[],\n logger: ILogger,\n fallbackAdapter: IModelAdapter\n): Promise<Map<VoterRole, IModelAdapter>> {\n let availableClis: CliName[];\n try {\n availableClis = await getAvailableClis();\n } catch (e: unknown) {\n logger.warn('Failed to resolve available CLIs; falling back to single adapter', {\n error: String(e),\n });\n availableClis = [];\n }\n\n if (availableClis.length <= 1) {\n logger.info('Using single adapter for all roles', { cliCount: availableClis.length });\n return assignUniformAdapter(roles, fallbackAdapter);\n }\n\n const cliAdapters = createCliAdapterMap(availableClis, logger);\n if (cliAdapters.size <= 1) return assignUniformAdapter(roles, fallbackAdapter);\n\n // Round-robin assign roles to diverse CLIs\n const cliList = [...cliAdapters.entries()];\n const adapters = new Map<VoterRole, IModelAdapter>();\n const assignments: Record<string, string> = {};\n for (let i = 0; i < roles.length; i++) {\n const role = roles[i];\n const entry = cliList[i % cliList.length];\n if (role === undefined || entry === undefined) continue;\n adapters.set(role, entry[1]);\n assignments[role] = entry[0];\n }\n\n logger.info('Diverse adapters assigned', {\n cliCount: cliAdapters.size,\n clis: [...cliAdapters.keys()],\n roleAssignments: assignments,\n });\n return adapters;\n}\n\n/** Options for staggered vote launching. */\ninterface StaggeredVoteInput {\n readonly roles: readonly VoterRole[];\n readonly proposal: string;\n readonly roleAdapters: Map<VoterRole, IModelAdapter>;\n readonly fallbackAdapter: IModelAdapter;\n readonly logger: ILogger;\n readonly voteOptions: { timeoutMs: number; maxRetries: number; allowSimulation: boolean };\n readonly interDelay: number;\n}\n\n/**\n * Launches votes with staggered delays to prevent rate limiting (Issue #1319)\n * and an overall wall-clock deadline to prevent indefinite hangs (Issue #1871).\n */\nasync function launchStaggeredVotes(\n input: StaggeredVoteInput\n): Promise<readonly AgentVoteResult[]> {\n const { roles, proposal, roleAdapters, fallbackAdapter, logger, voteOptions, interDelay } = input;\n // Raw \"worst legitimate completion\" estimate — retained unchanged so the\n // formula still answers \"how long could this vote take in principle?\".\n const computedDeadlineMs = computeOverallConsensusDeadlineMs(\n voteOptions.timeoutMs,\n voteOptions.maxRetries,\n roles.length,\n interDelay\n );\n // Clamp below the outer MCP tool-wrapper timeout. Without this, the\n // middleware kills the promise chain before launchVotesWithOverallDeadline\n // can produce structured partial results — clients see a naked timeout\n // error instead of a `source: 'error' / error: 'overall consensus deadline\n // exceeded'` vote per stuck role. (Issue #2105)\n const overallDeadlineMs = getMcpSafeDeadlineMs(computedDeadlineMs, 'consensus_vote');\n if (overallDeadlineMs < computedDeadlineMs) {\n logger.debug('Consensus deadline clamped to MCP wrapper timeout', {\n computedDeadlineMs,\n overallDeadlineMs,\n });\n }\n return launchVotesWithOverallDeadline({\n roles,\n proposal,\n roleAdapters,\n fallbackAdapter,\n logger,\n voteOptions,\n interDelay,\n overallDeadlineMs,\n voteFn: executeAgentVote,\n });\n}\n\n/**\n * Collects votes from multiple voter agents.\n *\n * Per Issue #280: No automatic simulation fallback. If no adapter is\n * available and simulation is not explicitly enabled, throws NoAdapterError.\n * Per Issue #845: Uses diverse CLIs when multiple are available.\n */\nexport async function collectRealVotes(\n options: CollectRealVotesOptions\n): Promise<readonly AgentVoteResult[]> {\n const logger = options.logger ?? defaultLogger;\n const { roles, proposal, simulate, allowSimulation } = options;\n const timeoutMs = options.timeoutMs ?? resolveVoteTimeout();\n const maxRetries = options.maxRetries ?? VOTE_TIMEOUTS.maxRetries;\n\n if (simulate === true) {\n logger.info('Using simulation mode (explicitly requested)');\n return createSimulatedVotes(roles, proposal);\n }\n\n const adapterResult = resolveAdapter(options, logger);\n\n if ('error' in adapterResult) {\n logger.error('No adapter available for voting', undefined, { error: adapterResult.error });\n\n if (allowSimulation === true) {\n logger.warn('Falling back to simulation (allowSimulation=true)');\n return createSimulatedVotes(roles, proposal, 'No adapter available');\n }\n\n throw new NoAdapterError(\n `No adapter available for voting: ${adapterResult.error}. ` +\n 'Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY.'\n );\n }\n\n // Per Issue #845: Use diverse adapters when no explicit adapter is provided\n const roleAdapters =\n options.adapter !== undefined\n ? assignUniformAdapter(roles, adapterResult.adapter)\n : await resolveDiverseAdapters(roles, logger, adapterResult.adapter);\n\n warnIfCodexConcurrencyExceeded(roleAdapters, logger);\n\n const voteOptions = { timeoutMs, maxRetries, allowSimulation: allowSimulation ?? false };\n const interDelay = options.interAgentDelayMs ?? DEFAULT_INTER_AGENT_DELAY_MS;\n\n return launchStaggeredVotes({\n roles,\n proposal,\n roleAdapters,\n fallbackAdapter: adapterResult.adapter,\n logger,\n voteOptions,\n interDelay,\n });\n}\n\n/**\n * Gets a description for a voter role.\n */\nexport function getRoleDescription(role: VoterRole): string {\n return VOTER_ROLES[role];\n}\n","/**\n * nexus-agents/consensus - Multi-Round Voting Protocol Types\n *\n * Multi-Round Voting Protocol Types (Issue #100)\n * Based on arXiv:2512.21352 - Multi-Agent Committees for Code Review\n */\n\nimport { z } from 'zod';\nimport type { Vote } from './types-core.js';\nimport { SUPERMAJORITY_THRESHOLD } from './types-core.js';\nimport { OPERATION_CLASSES } from '../config/timeouts.js';\n\n/**\n * Default per-round voting timeout (#3734). A voting round guards a parallel\n * MULTI-LLM panel, so it derives from the central `multi-llm-panel` runaway-guard\n * (900s) — not the old accidental 60s, which killed legitimate slow voters.\n */\nconst VOTING_ROUND_DEFAULT_TIMEOUT_MS = OPERATION_CLASSES['multi-llm-panel'].guardMs;\n\n/**\n * Voting round phases.\n * - analysis: Independent analysis (Round 1)\n * - deliberation: Share findings and discuss (Round 2)\n * - consensus: Final vote on recommendations (Round 3)\n */\nexport const VotingRoundPhaseSchema = z.enum(['analysis', 'deliberation', 'consensus']);\nexport type VotingRoundPhase = z.infer<typeof VotingRoundPhaseSchema>;\n\n/**\n * Voting round status.\n */\nexport const VotingRoundStatusSchema = z.enum([\n 'pending',\n 'in_progress',\n 'awaiting_votes',\n 'completed',\n 'aborted',\n]);\nexport type VotingRoundStatus = z.infer<typeof VotingRoundStatusSchema>;\n\n/**\n * A finding submitted by an agent during analysis.\n */\nexport const AgentFindingSchema = z.object({\n agentId: z.string(),\n category: z.enum(['bug', 'security', 'performance', 'style', 'design', 'documentation', 'other']),\n severity: z.enum(['critical', 'major', 'minor', 'suggestion']),\n description: z.string().min(1),\n location: z.string().optional().describe('File path and line range if applicable'),\n suggestion: z.string().optional().describe('Recommended fix'),\n confidence: z.number().min(0).max(1),\n timestamp: z.iso.datetime().optional(),\n});\nexport type AgentFinding = z.infer<typeof AgentFindingSchema>;\n\n/**\n * Finding vote during deliberation.\n */\nexport const FindingVoteSchema = z.object({\n agentId: z.string(),\n findingId: z.string(),\n agree: z.boolean(),\n reasoning: z.string().optional(),\n amendedSeverity: z.enum(['critical', 'major', 'minor', 'suggestion']).optional(),\n});\nexport type FindingVote = z.infer<typeof FindingVoteSchema>;\n\n/**\n * A single voting round in the protocol.\n */\nexport interface VotingRound {\n id: string;\n phase: VotingRoundPhase;\n status: VotingRoundStatus;\n findings: Map<string, AgentFinding>; // findingId -> finding\n findingVotes: Map<string, FindingVote[]>; // findingId -> votes\n finalVotes: Map<string, Vote>; // agentId -> final vote\n startedAt: string;\n completedAt?: string;\n roundNumber: number;\n}\n\n/**\n * Configuration for the voting protocol.\n */\nexport interface VotingProtocolConfig {\n /** Number of agents in the committee (default: 3) */\n committeeSize: number;\n /** Maximum rounds before forcing decision (default: 3) */\n maxRounds: number;\n /** Timeout per round in milliseconds (default: multi-llm-panel guard, 900000) */\n roundTimeoutMs: number;\n /** Minimum agreement threshold (default: 0.67) */\n agreementThreshold: number;\n /** Enable anti-sycophancy detection (default: true) */\n enableAntiSycophancy: boolean;\n /** Similarity threshold for sycophancy detection (default: 0.8) */\n sycophancyThreshold: number;\n}\n\nexport const VotingProtocolConfigSchema = z.object({\n committeeSize: z.number().int().min(2).max(7).default(3),\n maxRounds: z.number().int().min(1).max(5).default(3),\n roundTimeoutMs: z.number().int().positive().default(VOTING_ROUND_DEFAULT_TIMEOUT_MS),\n agreementThreshold: z.number().min(0.5).max(1).default(SUPERMAJORITY_THRESHOLD),\n enableAntiSycophancy: z.boolean().default(true),\n sycophancyThreshold: z.number().min(0).max(1).default(0.8),\n});\n\nexport const DEFAULT_VOTING_PROTOCOL_CONFIG: VotingProtocolConfig = {\n committeeSize: 3,\n maxRounds: 3,\n roundTimeoutMs: VOTING_ROUND_DEFAULT_TIMEOUT_MS,\n // Default agreement level IS the supermajority (2/3) — single source (#3571).\n agreementThreshold: SUPERMAJORITY_THRESHOLD,\n enableAntiSycophancy: true,\n sycophancyThreshold: 0.8,\n};\n\n/**\n * Session state for a voting protocol instance.\n */\nexport interface VotingSession {\n id: string;\n topic: string;\n committee: string[]; // Agent IDs\n rounds: VotingRound[];\n currentRound: number;\n config: VotingProtocolConfig;\n status: 'active' | 'completed' | 'aborted';\n createdAt: string;\n completedAt?: string;\n finalResult?: VotingProtocolResult;\n}\n\n/**\n * Final result of a voting protocol session.\n */\nexport interface VotingProtocolResult {\n sessionId: string;\n topic: string;\n outcome: 'approved' | 'rejected' | 'needs_revision' | 'no_consensus';\n consolidatedFindings: ConsolidatedFinding[];\n roundSummaries: RoundSummary[];\n agreementScore: number;\n sycophancyDetected: boolean;\n totalDurationMs: number;\n participatingAgents: string[];\n}\n\n/**\n * A consolidated finding after deliberation.\n */\nexport interface ConsolidatedFinding {\n id: string;\n category: AgentFinding['category'];\n severity: AgentFinding['severity'];\n description: string;\n location?: string;\n suggestion?: string;\n supportingAgents: string[];\n agreementRatio: number;\n originalFindings: AgentFinding[];\n}\n\n/**\n * Summary of a single round.\n */\nexport interface RoundSummary {\n roundNumber: number;\n phase: VotingRoundPhase;\n findingsCount: number;\n votesCount: number;\n agreementScore: number;\n durationMs: number;\n}\n\n/**\n * Interface for the multi-round voting protocol.\n * (Source: Issue #100, arXiv:2512.21352)\n */\nexport interface IVotingProtocol {\n /** Create a new voting session with a committee */\n createSession(\n topic: string,\n committee: string[],\n config?: Partial<VotingProtocolConfig>\n ): VotingSession;\n\n /** Start the analysis round (Round 1) */\n startAnalysisRound(sessionId: string): Promise<VotingRound>;\n\n /** Submit findings from an agent during analysis */\n submitFindings(sessionId: string, agentId: string, findings: AgentFinding[]): Promise<void>;\n\n /** Start the deliberation round (Round 2) */\n startDeliberationRound(sessionId: string): Promise<VotingRound>;\n\n /** Vote on findings during deliberation */\n voteOnFinding(sessionId: string, vote: FindingVote): Promise<void>;\n\n /** Start the consensus round (Round 3) */\n startConsensusRound(sessionId: string): Promise<VotingRound>;\n\n /** Submit final vote during consensus */\n submitFinalVote(sessionId: string, agentId: string, vote: Vote): Promise<void>;\n\n /** Get the final result (closes session if complete) */\n getResult(sessionId: string): Promise<VotingProtocolResult | null>;\n\n /** Check for sycophancy in the current round */\n detectSycophancy(sessionId: string): SycophancyReport;\n\n /** Get the current session state */\n getSession(sessionId: string): VotingSession | undefined;\n}\n\n/**\n * Report from sycophancy detection.\n */\nexport interface SycophancyReport {\n detected: boolean;\n confidenceScore: number;\n indicators: SycophancyIndicator[];\n affectedAgents: string[];\n recommendation: string;\n}\n\n/**\n * Individual sycophancy indicator.\n */\nexport interface SycophancyIndicator {\n type: 'premature_consensus' | 'opinion_convergence' | 'confidence_inflation' | 'echo_chamber';\n description: string;\n severity: 'low' | 'medium' | 'high';\n agents: string[];\n}\n","/**\n * nexus-agents/consensus - Weighted Byzantine Voting Types\n *\n * Weighted Byzantine Voting Types (Issue #103)\n * Based on CP-WBFT (arXiv:2511.10400)\n */\n\nimport { z } from 'zod';\nimport type { Vote } from './types-core.js';\nimport { SUPERMAJORITY_THRESHOLD } from './types-core.js';\n\n/**\n * Task outcome STATUS for tracking agent performance — a 4-state vote status,\n * NOT an outcome row. Named `*Status` to avoid colliding with the canonical\n * outcome *record* `TaskOutcome` in orchestration/outcomes (#3146/#3226: the\n * two were unrelated types that happened to share the name `TaskOutcome`).\n */\nexport const TaskOutcomeStatusSchema = z.enum(['success', 'failure', 'partial', 'unknown']);\nexport type TaskOutcomeStatus = z.infer<typeof TaskOutcomeStatusSchema>;\n\n/**\n * Extended agent performance with Byzantine detection.\n */\nexport interface WeightedAgentRecord {\n readonly agentId: string;\n readonly totalTasks: number;\n readonly successfulTasks: number;\n readonly failedTasks: number;\n readonly partialTasks: number;\n readonly successRate: number;\n readonly weight: number;\n readonly trustScore: number;\n readonly byzantineFlags: number;\n readonly lastActive: Date;\n readonly createdAt: Date;\n}\n\nexport const WeightedAgentRecordSchema = z.object({\n agentId: z.string().min(1),\n totalTasks: z.number().int().nonnegative(),\n successfulTasks: z.number().int().nonnegative(),\n failedTasks: z.number().int().nonnegative(),\n partialTasks: z.number().int().nonnegative(),\n successRate: z.number().min(0).max(1),\n weight: z.number().min(0).max(1),\n trustScore: z.number().min(0).max(1),\n byzantineFlags: z.number().int().nonnegative(),\n lastActive: z.date(),\n createdAt: z.date(),\n});\n\n/**\n * Weighted consensus result.\n */\nexport interface WeightedConsensusResult {\n readonly decision: 'approve' | 'reject' | 'no_consensus';\n readonly weightedApproval: number;\n readonly weightedRejection: number;\n readonly totalWeight: number;\n readonly quorumReached: boolean;\n readonly byzantineDetected: boolean;\n readonly participatingAgents: readonly string[];\n readonly weightBreakdown: ReadonlyMap<string, number>;\n}\n\n/**\n * Configuration for weighted Byzantine voting.\n */\nexport interface WeightedVotingConfig {\n /** Minimum weight to participate in voting (default: 0.1) */\n readonly minWeight: number;\n /** Maximum Byzantine fault tolerance (default: 0.33) */\n readonly maxByzantineFraction: number;\n /** Weight decay factor per failed task (default: 0.9) */\n readonly weightDecayFactor: number;\n /** Weight recovery factor per successful task (default: 1.05) */\n readonly weightRecoveryFactor: number;\n /** Trust score required to vote (default: 0.3) */\n readonly minTrustScore: number;\n /** Byzantine flag threshold for exclusion (default: 3) */\n readonly byzantineFlagThreshold: number;\n /** Initial weight for new agents (default: 0.5) */\n readonly initialWeight: number;\n /** Quorum threshold for valid consensus (default: 0.67) */\n readonly quorumThreshold: number;\n}\n\nexport const WeightedVotingConfigSchema = z.object({\n minWeight: z.number().min(0).max(1).default(0.1),\n maxByzantineFraction: z.number().min(0).max(0.5).default(0.33),\n weightDecayFactor: z.number().min(0.5).max(1).default(0.9),\n weightRecoveryFactor: z.number().min(1).max(2).default(1.05),\n minTrustScore: z.number().min(0).max(1).default(0.3),\n byzantineFlagThreshold: z.number().int().positive().default(3),\n initialWeight: z.number().min(0).max(1).default(0.5),\n quorumThreshold: z.number().min(0.5).max(1).default(SUPERMAJORITY_THRESHOLD),\n});\n\nexport const DEFAULT_WEIGHTED_VOTING_CONFIG: WeightedVotingConfig = {\n minWeight: 0.1,\n maxByzantineFraction: 0.33,\n weightDecayFactor: 0.9,\n weightRecoveryFactor: 1.05,\n minTrustScore: 0.3,\n byzantineFlagThreshold: 3,\n initialWeight: 0.5,\n // Default quorum IS the supermajority (2/3) — single source (#3571).\n quorumThreshold: SUPERMAJORITY_THRESHOLD,\n};\n\n/**\n * Interface for weighted Byzantine voting.\n * (Source: Issue #103, arXiv:2511.10400 - CP-WBFT)\n */\nexport interface IWeightedVoting {\n /** Calculate vote weight for an agent */\n calculateWeight(agentId: string): number;\n\n /** Update agent performance based on task outcome */\n updatePerformance(agentId: string, outcome: TaskOutcomeStatus): void;\n\n /** Run weighted consensus on votes */\n weightedConsensus(votes: ReadonlyMap<string, Vote>): WeightedConsensusResult;\n\n /** Register a new agent */\n registerAgent(agentId: string): void;\n\n /** Get agent performance record */\n getAgentRecord(agentId: string): WeightedAgentRecord | undefined;\n\n /** Flag agent for Byzantine behavior */\n flagByzantine(agentId: string, reason: string): void;\n\n /** Get all agent records */\n getAllRecords(): readonly WeightedAgentRecord[];\n\n /** Check if agent can vote */\n canVote(agentId: string): boolean;\n\n /** Recalibrate all weights based on global performance */\n recalibrateWeights(): void;\n}\n","/**\n * nexus-agents/consensus - Higher-Order Voting Types\n *\n * Type definitions for Opinion-Wise (OW) and Independent Subset Partition (ISP)\n * voting methods that account for correlations between agent opinions.\n *\n * Higher-order voting uses Bayesian-optimal aggregation that handles correlated\n * agents better than traditional independent voting assumptions.\n *\n * @module consensus/higher-order-types\n * (Source: Issue #333)\n */\n\nimport { z } from 'zod';\nimport type { Vote, VoteDecision } from './types-core.js';\n\n// ============================================================================\n// CORRELATION TYPES\n// ============================================================================\n\n/**\n * Pair of agent IDs for correlation tracking.\n * Stored as \"agentA:agentB\" where agentA < agentB lexicographically.\n */\nexport type AgentPairKey = `${string}:${string}`;\n\n/**\n * Creates a canonical agent pair key for correlation lookup.\n * Orders agents lexicographically to ensure consistent keys.\n */\nexport function createAgentPairKey(agentA: string, agentB: string): AgentPairKey {\n return agentA < agentB ? `${agentA}:${agentB}` : `${agentB}:${agentA}`;\n}\n\n/**\n * Extracts agent IDs from a pair key.\n */\nexport function parseAgentPairKey(key: AgentPairKey): [string, string] {\n const parts = key.split(':');\n if (parts.length !== 2 || parts[0] === undefined || parts[1] === undefined) {\n throw new Error(`Invalid agent pair key: ${key}`);\n }\n return [parts[0], parts[1]];\n}\n\n/**\n * Correlation coefficient between two agents' voting patterns.\n * Range: -1 (perfectly anti-correlated) to +1 (perfectly correlated).\n * 0 indicates independence.\n */\nexport const CorrelationCoefficientSchema = z.number().min(-1).max(1);\nexport type CorrelationCoefficient = z.infer<typeof CorrelationCoefficientSchema>;\n\n/**\n * Correlation matrix storing pairwise correlations between agents.\n */\nexport type CorrelationMatrix = Map<AgentPairKey, CorrelationCoefficient>;\n\n/**\n * A subset of agents that vote independently of each other.\n * Used in ISP (Independent Subset Partition) method.\n */\nexport interface IndependentSubset {\n /** Unique identifier for this subset */\n readonly id: string;\n /** Agent IDs in this independent subset */\n readonly agentIds: readonly string[];\n /** Average internal independence score (lower = more independent) */\n readonly independenceScore: number;\n /** Number of observations supporting this grouping */\n readonly observationCount: number;\n}\n\nexport const IndependentSubsetSchema = z.object({\n id: z.string(),\n agentIds: z.array(z.string()),\n independenceScore: z.number().min(0).max(1),\n observationCount: z.number().int().nonnegative(),\n});\n\n// ============================================================================\n// VOTING HISTORY TYPES\n// ============================================================================\n\n/**\n * Record of a single voting observation for correlation tracking.\n */\nexport interface VotingObservation {\n /** Unique proposal ID */\n readonly proposalId: string;\n /** Agent who cast the vote */\n readonly agentId: string;\n /** The vote decision */\n readonly decision: VoteDecision;\n /** Confidence level (0-1) */\n readonly confidence: number;\n /** Whether the vote aligned with the final outcome */\n readonly alignedWithOutcome: boolean;\n /** Timestamp of the vote */\n readonly timestamp: Date;\n}\n\nexport const VotingObservationSchema = z.object({\n proposalId: z.string(),\n agentId: z.string(),\n decision: z.enum(['approve', 'reject', 'abstain']),\n confidence: z.number().min(0).max(1),\n alignedWithOutcome: z.boolean(),\n timestamp: z.date(),\n});\n\n/**\n * Aggregated voting history for a pair of agents.\n */\nexport interface PairwiseVotingHistory {\n /** Agent pair key */\n readonly pairKey: AgentPairKey;\n /** Number of proposals where both agents voted */\n readonly jointObservations: number;\n /** Number of times both agents agreed */\n readonly agreements: number;\n /** Number of times agents disagreed */\n readonly disagreements: number;\n /** Computed correlation coefficient */\n readonly correlation: CorrelationCoefficient;\n /** Last update timestamp */\n readonly lastUpdated: Date;\n}\n\nexport const PairwiseVotingHistorySchema = z.object({\n pairKey: z.string() as z.ZodType<AgentPairKey>,\n jointObservations: z.number().int().nonnegative(),\n agreements: z.number().int().nonnegative(),\n disagreements: z.number().int().nonnegative(),\n correlation: CorrelationCoefficientSchema,\n lastUpdated: z.date(),\n});\n\n// ============================================================================\n// HIGHER-ORDER VOTING CONFIG\n// ============================================================================\n\n/**\n * Configuration for higher-order voting.\n */\nexport interface HigherOrderVotingConfig {\n /** Minimum observations before using correlation data (default: 10) */\n readonly minObservationsForCorrelation: number;\n /** Correlation threshold to consider agents correlated (default: 0.3) */\n readonly correlationThreshold: number;\n /** Maximum correlation age in milliseconds before recalculation (default: 24h) */\n readonly correlationMaxAgeMs: number;\n /** Independence threshold for ISP grouping (default: 0.2) */\n readonly independenceThreshold: number;\n /** Whether to fall back to simple voting when correlation data insufficient */\n readonly fallbackToSimpleVoting: boolean;\n /** Decay factor for old observations (0-1, default: 0.95) */\n readonly observationDecayFactor: number;\n /** Maximum observations to store per agent before FIFO eviction (default: 1000) */\n readonly maxObservationsPerAgent: number;\n /** Maximum total proposals to track before evicting oldest (default: 5000) */\n readonly maxProposals: number;\n /** Maximum pairwise history entries before LRU eviction (default: 100) */\n readonly maxTrackedPairs: number;\n}\n\nexport const HigherOrderVotingConfigSchema = z.object({\n minObservationsForCorrelation: z.number().int().positive().default(10),\n correlationThreshold: z.number().min(0).max(1).default(0.3),\n correlationMaxAgeMs: z.number().int().positive().default(86400000), // 24 hours\n independenceThreshold: z.number().min(0).max(1).default(0.2),\n fallbackToSimpleVoting: z.boolean().default(true),\n observationDecayFactor: z.number().min(0).max(1).default(0.95),\n maxObservationsPerAgent: z.number().int().positive().default(1000),\n maxProposals: z.number().int().positive().default(5000),\n maxTrackedPairs: z.number().int().positive().default(100),\n});\n\nexport const DEFAULT_HIGHER_ORDER_CONFIG: HigherOrderVotingConfig = {\n minObservationsForCorrelation: 10,\n correlationThreshold: 0.3,\n correlationMaxAgeMs: 86400000, // 24 hours\n independenceThreshold: 0.2,\n fallbackToSimpleVoting: true,\n observationDecayFactor: 0.95,\n maxObservationsPerAgent: 1000,\n maxProposals: 5000,\n maxTrackedPairs: 100,\n};\n\n// ============================================================================\n// HIGHER-ORDER VOTING RESULTS\n// ============================================================================\n\n/**\n * Result of Bayesian aggregation with correlation awareness.\n */\nexport interface HigherOrderVotingResult {\n /** Final decision */\n readonly decision: 'approve' | 'reject' | 'no_consensus';\n /** Posterior probability of approval */\n readonly posteriorApproval: number;\n /** Posterior probability of rejection */\n readonly posteriorRejection: number;\n /** Effective number of independent votes */\n readonly effectiveVoteCount: number;\n /** Whether correlation data was sufficient */\n readonly usedCorrelationData: boolean;\n /** Method used: 'ow' (opinion-wise), 'isp', or 'simple' (fallback) */\n readonly method: 'ow' | 'isp' | 'simple';\n /** Improvement over baseline majority voting (percentage points) */\n readonly improvementOverBaseline: number;\n /** Independent subsets used (if ISP method) */\n readonly independentSubsets?: readonly IndependentSubset[];\n /** Agents whose votes were down-weighted due to correlation */\n readonly downweightedAgents: readonly string[];\n /** Reasoning for the decision */\n readonly reasoning: string;\n}\n\nexport const HigherOrderVotingResultSchema = z.object({\n decision: z.enum(['approve', 'reject', 'no_consensus']),\n posteriorApproval: z.number().min(0).max(1),\n posteriorRejection: z.number().min(0).max(1),\n effectiveVoteCount: z.number().nonnegative(),\n usedCorrelationData: z.boolean(),\n method: z.enum(['ow', 'isp', 'simple']),\n improvementOverBaseline: z.number(),\n independentSubsets: z.array(IndependentSubsetSchema).optional(),\n downweightedAgents: z.array(z.string()),\n reasoning: z.string(),\n});\n\n// ============================================================================\n// CORRELATION TRACKER INTERFACE\n// ============================================================================\n\n/**\n * Statistics about correlation tracking.\n */\nexport interface CorrelationTrackerStats {\n /** Total agents being tracked */\n readonly totalAgents: number;\n /** Total agent pairs with correlation data */\n readonly trackedPairs: number;\n /** Total voting observations recorded */\n readonly totalObservations: number;\n /** Average correlation across all pairs */\n readonly averageCorrelation: number;\n /** Number of identified independent subsets */\n readonly independentSubsetCount: number;\n /** Pairs with sufficient data for correlation calculation */\n readonly pairsWithSufficientData: number;\n}\n\nexport const CorrelationTrackerStatsSchema = z.object({\n totalAgents: z.number().int().nonnegative(),\n trackedPairs: z.number().int().nonnegative(),\n totalObservations: z.number().int().nonnegative(),\n averageCorrelation: z.number(),\n independentSubsetCount: z.number().int().nonnegative(),\n pairsWithSufficientData: z.number().int().nonnegative(),\n});\n\n/**\n * Interface for correlation tracking between agents.\n */\nexport interface ICorrelationTracker {\n /**\n * Record a vote and its outcome for correlation tracking.\n */\n recordVote(agentId: string, vote: Vote, outcome: 'approved' | 'rejected'): void;\n\n /**\n * Record votes from multiple agents for the same proposal.\n */\n recordProposalVotes(\n proposalId: string,\n votes: ReadonlyMap<string, Vote>,\n outcome: 'approved' | 'rejected'\n ): void;\n\n /**\n * Compute the full correlation matrix for all tracked agents.\n */\n computeCorrelationMatrix(): CorrelationMatrix;\n\n /**\n * Get correlation between two specific agents.\n * Returns undefined if insufficient data.\n */\n getCorrelation(agentA: string, agentB: string): CorrelationCoefficient | undefined;\n\n /**\n * Identify groups of agents that vote independently.\n */\n identifyIndependentSubsets(): readonly IndependentSubset[];\n\n /**\n * Check if there is sufficient correlation data for a set of agents.\n */\n hasSufficientData(agentIds: readonly string[]): boolean;\n\n /**\n * Get statistics about the correlation tracker.\n */\n getStats(): CorrelationTrackerStats;\n\n /**\n * Clear all recorded data.\n */\n clear(): void;\n}\n\n// ============================================================================\n// OW VOTING INTERFACE\n// ============================================================================\n\n/**\n * Interface for Opinion-Wise higher-order voting.\n */\nexport interface IHigherOrderVoting {\n /**\n * Aggregate votes using Bayesian correlation-aware method.\n */\n aggregateWithCorrelation(\n votes: ReadonlyMap<string, Vote>,\n correlationMatrix: CorrelationMatrix\n ): HigherOrderVotingResult;\n\n /**\n * Estimate correlation matrix from voting history.\n */\n estimateCorrelation(tracker: ICorrelationTracker): CorrelationMatrix;\n\n /**\n * Compute result using Independent Subset Partition method.\n */\n computeISP(\n votes: ReadonlyMap<string, Vote>,\n independentSubsets: readonly IndependentSubset[]\n ): HigherOrderVotingResult;\n\n /**\n * Full pipeline: estimate correlation, compute result.\n */\n aggregate(\n votes: ReadonlyMap<string, Vote>,\n tracker: ICorrelationTracker\n ): HigherOrderVotingResult;\n\n /**\n * Get the current configuration.\n */\n getConfig(): HigherOrderVotingConfig;\n}\n","/**\n * nexus-agents/consensus - Higher-Order Voting Helpers\n *\n * Helper functions for Opinion-Wise (OW) and Independent Subset Partition (ISP)\n * voting methods. Extracted from higher-order-voting.ts to maintain file size limits.\n *\n * @module consensus/higher-order-helpers\n * (Source: Issue #333, #339)\n */\n\nimport type { Vote } from './types-core.js';\nimport type {\n CorrelationMatrix,\n HigherOrderVotingResult,\n IndependentSubset,\n} from './higher-order-types.js';\nimport { createAgentPairKey } from './higher-order-types.js';\n\n/**\n * Result of Bayesian aggregation.\n */\nexport interface BayesianAggregateResult {\n readonly posteriorApproval: number;\n readonly posteriorRejection: number;\n readonly effectiveVoteCount: number;\n readonly downweightedAgents: string[];\n}\n\n/**\n * Result of subset aggregation.\n */\nexport interface SubsetAggregationResult {\n readonly subsetResults: Array<{ approval: number; rejection: number; weight: number }>;\n readonly downweightedAgents: string[];\n}\n\n/**\n * Result of combined subset results.\n */\nexport interface CombinedSubsetResult {\n readonly posteriorApproval: number;\n readonly posteriorRejection: number;\n readonly totalWeight: number;\n}\n\n/**\n * Check if there is sufficient correlation data for analysis.\n */\nexport function hasSufficientCorrelationData(\n agentIds: readonly string[],\n correlationMatrix: CorrelationMatrix\n): boolean {\n if (agentIds.length < 2) return false;\n\n let pairsWithData = 0;\n const totalPairs = (agentIds.length * (agentIds.length - 1)) / 2;\n\n for (let i = 0; i < agentIds.length; i++) {\n for (let j = i + 1; j < agentIds.length; j++) {\n const agentA = agentIds[i];\n const agentB = agentIds[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n if (correlationMatrix.has(pairKey)) {\n pairsWithData++;\n }\n }\n }\n }\n\n return pairsWithData >= Math.ceil(totalPairs * 0.5);\n}\n\n/**\n * Compute effective weights for agents based on correlations.\n * Reduces weights for highly correlated agents.\n */\nexport function computeEffectiveWeights(\n agentIds: readonly string[],\n correlationMatrix: CorrelationMatrix,\n correlationThreshold: number\n): Map<string, number> {\n const weights = new Map<string, number>();\n\n // Start with equal weights\n for (const agentId of agentIds) {\n weights.set(agentId, 1.0);\n }\n\n // Reduce weights for highly correlated agents\n for (let i = 0; i < agentIds.length; i++) {\n for (let j = i + 1; j < agentIds.length; j++) {\n const agentA = agentIds[i];\n const agentB = agentIds[j];\n if (agentA === undefined || agentB === undefined) continue;\n\n const pairKey = createAgentPairKey(agentA, agentB);\n const correlation = correlationMatrix.get(pairKey);\n\n if (correlation !== undefined && correlation > correlationThreshold) {\n // Reduce weight proportionally to correlation\n const reduction = correlation * 0.5;\n const currentWeightA = weights.get(agentA) ?? 1.0;\n const currentWeightB = weights.get(agentB) ?? 1.0;\n\n // Apply reduction to both agents (but less to avoid over-penalizing)\n weights.set(agentA, Math.max(0.1, currentWeightA - reduction * 0.5));\n weights.set(agentB, Math.max(0.1, currentWeightB - reduction * 0.5));\n }\n }\n }\n\n // NOTE (#3172, investigated + rejected): a \"restore uniform weights when all\n // collapse to the floor\" guard was considered but is incorrect. When agents\n // are equally correlated, equal downweighting is the CORRECT behavior (they\n // are equally redundant), and because the Bayesian aggregate is a weighted\n // average, scaling all weights equally is invariant — all-at-floor yields the\n // same posterior as uniform, so it is not degenerate. Restoring uniform would\n // wrongly treat correlated agents as independent and inflate the effective\n // vote count (guarded by the \"all perfectly correlated\" test).\n\n return weights;\n}\n\n/**\n * Perform Bayesian aggregation of votes with effective weights.\n */\nexport function bayesianAggregate(\n votes: ReadonlyMap<string, Vote>,\n effectiveWeights: Map<string, number>\n): BayesianAggregateResult {\n let weightedApproval = 0;\n let weightedRejection = 0;\n let totalWeight = 0;\n const downweightedAgents: string[] = [];\n\n for (const [agentId, vote] of votes) {\n const weight = effectiveWeights.get(agentId) ?? 1.0;\n\n // Track downweighted agents\n if (weight < 0.8) {\n downweightedAgents.push(agentId);\n }\n\n // Weight by confidence and effective weight\n const effectiveWeight = weight * vote.confidence;\n totalWeight += effectiveWeight;\n\n if (vote.decision === 'approve') {\n weightedApproval += effectiveWeight;\n } else if (vote.decision === 'reject') {\n weightedRejection += effectiveWeight;\n }\n // Abstains contribute to total weight but not to either side\n }\n\n const posteriorApproval = totalWeight > 0 ? weightedApproval / totalWeight : 0.5;\n const posteriorRejection = totalWeight > 0 ? weightedRejection / totalWeight : 0.5;\n const effectiveVoteCount = totalWeight;\n\n return { posteriorApproval, posteriorRejection, effectiveVoteCount, downweightedAgents };\n}\n\n/**\n * Aggregate votes within independent subsets.\n */\nexport function aggregateSubsets(\n votes: ReadonlyMap<string, Vote>,\n independentSubsets: readonly IndependentSubset[]\n): SubsetAggregationResult {\n const subsetResults: Array<{ approval: number; rejection: number; weight: number }> = [];\n const downweightedAgents: string[] = [];\n\n for (const subset of independentSubsets) {\n const subsetVotes = new Map<string, Vote>();\n for (const agentId of subset.agentIds) {\n const vote = votes.get(agentId);\n if (vote !== undefined) subsetVotes.set(agentId, vote);\n }\n if (subsetVotes.size === 0) continue;\n\n const { approval, rejection } = countSubsetVotes(subsetVotes);\n const weight = subsetVotes.size * (1 - subset.independenceScore);\n subsetResults.push({ approval, rejection, weight });\n\n if (subset.agentIds.length === 1) downweightedAgents.push(...subset.agentIds);\n }\n return { subsetResults, downweightedAgents };\n}\n\n/**\n * Combine subset results into overall posterior probabilities.\n */\nexport function combineSubsetResults(\n subsetResults: readonly { approval: number; rejection: number; weight: number }[]\n): CombinedSubsetResult {\n let totalApproval = 0;\n let totalRejection = 0;\n let totalWeight = 0;\n for (const { approval, rejection, weight } of subsetResults) {\n totalApproval += approval * weight;\n totalRejection += rejection * weight;\n totalWeight += weight;\n }\n return {\n posteriorApproval: totalWeight > 0 ? totalApproval / totalWeight : 0.5,\n posteriorRejection: totalWeight > 0 ? totalRejection / totalWeight : 0.5,\n totalWeight,\n };\n}\n\n/**\n * Count votes within a subset, weighted by confidence.\n */\nexport function countSubsetVotes(votes: ReadonlyMap<string, Vote>): {\n approval: number;\n rejection: number;\n} {\n let approval = 0;\n let rejection = 0;\n\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') {\n approval += vote.confidence;\n } else if (vote.decision === 'reject') {\n rejection += vote.confidence;\n }\n }\n\n const total = approval + rejection;\n return {\n approval: total > 0 ? approval / total : 0.5,\n rejection: total > 0 ? rejection / total : 0.5,\n };\n}\n\n/**\n * Determine decision based on posterior probabilities.\n */\nexport function determineHigherOrderDecision(\n posteriorApproval: number,\n posteriorRejection: number\n): 'approve' | 'reject' | 'no_consensus' {\n const diff = Math.abs(posteriorApproval - posteriorRejection);\n\n // Require significant margin for decision\n if (diff < 0.1) {\n return 'no_consensus';\n }\n\n return posteriorApproval > posteriorRejection ? 'approve' : 'reject';\n}\n\n/**\n * Perform simple majority aggregation (no correlation data).\n */\nexport function aggregateSimple(\n votes: ReadonlyMap<string, Vote>,\n buildReasoningFn: (\n decision: 'approve' | 'reject' | 'no_consensus',\n effectiveVotes: number,\n downweightedAgents: string[],\n method: 'ow' | 'isp' | 'simple'\n ) => string\n): HigherOrderVotingResult {\n let approve = 0;\n let reject = 0;\n let total = 0;\n\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') {\n approve++;\n } else if (vote.decision === 'reject') {\n reject++;\n }\n if (vote.decision !== 'abstain') {\n total++;\n }\n }\n\n const posteriorApproval = total > 0 ? approve / total : 0.5;\n const posteriorRejection = total > 0 ? reject / total : 0.5;\n const decision = determineHigherOrderDecision(posteriorApproval, posteriorRejection);\n\n return {\n decision,\n posteriorApproval,\n posteriorRejection,\n effectiveVoteCount: total,\n usedCorrelationData: false,\n method: 'simple',\n improvementOverBaseline: 0,\n downweightedAgents: [],\n reasoning: buildReasoningFn(decision, total, [], 'simple'),\n };\n}\n\n/**\n * Calculate improvement over baseline.\n */\nexport function calculateImprovement(\n posteriorApproval: number,\n posteriorRejection: number,\n decision: 'approve' | 'reject' | 'no_consensus',\n baseline: HigherOrderVotingResult\n): number {\n // Improvement is measured by increased confidence in the same direction\n if (decision === 'no_consensus' || baseline.decision === 'no_consensus') {\n return 0;\n }\n\n const currentConfidence = decision === 'approve' ? posteriorApproval : posteriorRejection;\n const baselineConfidence =\n baseline.decision === 'approve' ? baseline.posteriorApproval : baseline.posteriorRejection;\n\n // Return improvement as percentage points\n return (currentConfidence - baselineConfidence) * 100;\n}\n\n/**\n * Build reasoning string for voting result.\n */\nexport function buildReasoning(\n decision: 'approve' | 'reject' | 'no_consensus',\n effectiveVotes: number,\n downweightedAgents: readonly string[],\n method: 'ow' | 'isp' | 'simple'\n): string {\n const methodName =\n method === 'ow'\n ? 'Opinion-Wise Bayesian aggregation'\n : method === 'isp'\n ? 'Independent Subset Partition'\n : 'simple majority voting';\n\n let reasoning = `Decision reached via ${methodName} with ${effectiveVotes.toFixed(1)} effective votes. `;\n\n if (downweightedAgents.length > 0) {\n reasoning += `${String(downweightedAgents.length)} agent(s) downweighted due to correlation. `;\n }\n\n if (decision === 'no_consensus') {\n reasoning += 'No consensus reached due to insufficient margin.';\n } else {\n reasoning += `Final decision: ${decision}.`;\n }\n\n return reasoning;\n}\n","/**\n * nexus-agents/consensus - Higher-Order Voting Implementation\n *\n * Implements Opinion-Wise (OW) and Independent Subset Partition (ISP) voting\n * methods that account for correlations between agent opinions.\n *\n * Traditional voting assumes independence between voters. Higher-order voting\n * uses Bayesian-optimal aggregation that handles correlated agents better,\n * resulting in more accurate consensus decisions.\n *\n * @module consensus/higher-order-voting\n * (Source: Issue #333)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport type { Vote, VoteCounts } from './types-core.js';\nimport type {\n IHigherOrderVoting,\n ICorrelationTracker,\n CorrelationMatrix,\n HigherOrderVotingConfig,\n HigherOrderVotingResult,\n IndependentSubset,\n} from './higher-order-types.js';\nimport { DEFAULT_HIGHER_ORDER_CONFIG } from './higher-order-types.js';\nimport type { IVotingStrategy, VotingOutcome } from './strategies.js';\nimport type { ConsensusAlgorithm } from './types-core.js';\nimport {\n hasSufficientCorrelationData,\n computeEffectiveWeights,\n bayesianAggregate,\n aggregateSubsets,\n combineSubsetResults,\n determineHigherOrderDecision,\n aggregateSimple,\n calculateImprovement,\n buildReasoning,\n} from './higher-order-helpers.js';\n\nconst logger = createLogger({ component: 'higher-order-voting' });\n\n/** Options for creating OWVoting instance. */\nexport interface OWVotingOptions {\n readonly config?: Partial<HigherOrderVotingConfig>;\n /**\n * Algorithm label this instance reports (#3168). Defaults to `simple_majority`\n * for backward compatibility; `HigherOrderVotingStrategy` sets `opinion_wise`.\n * Keeps the label consistent whether constructed directly or via a factory.\n */\n readonly algorithm?: ConsensusAlgorithm;\n}\n\n/**\n * Opinion-Wise higher-order voting implementation.\n * Uses Bayesian aggregation with correlation awareness.\n */\nexport class OWVoting implements IHigherOrderVoting, IVotingStrategy {\n readonly algorithm: ConsensusAlgorithm;\n private readonly config: HigherOrderVotingConfig;\n\n constructor(options: OWVotingOptions = {}) {\n this.config = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...options.config };\n // #3168: configurable so the label is correct whether built directly or via\n // a factory; defaults to simple_majority for backward compatibility.\n this.algorithm = options.algorithm ?? 'simple_majority';\n logger.info('OWVoting initialized', { config: this.config, algorithm: this.algorithm });\n }\n\n /** IVotingStrategy implementation for integration with ConsensusEngine. */\n calculateOutcome(votes: Map<string, Vote>, _weights?: Map<string, number>): VotingOutcome {\n const result = this.aggregateSimpleInternal(votes);\n return this.toVotingOutcome(votes, result);\n }\n\n aggregateWithCorrelation(\n votes: ReadonlyMap<string, Vote>,\n correlationMatrix: CorrelationMatrix\n ): HigherOrderVotingResult {\n const agentIds = Array.from(votes.keys());\n const hasSufficientData = hasSufficientCorrelationData(agentIds, correlationMatrix);\n\n if (!hasSufficientData && this.config.fallbackToSimpleVoting) {\n // Issue #525: Log at INFO level for visibility\n logger.info('Insufficient correlation data, falling back to simple voting', {\n agentCount: agentIds.length,\n reason: 'insufficient_correlation_data',\n });\n return this.aggregateSimpleInternal(votes);\n }\n\n const effectiveWeights = computeEffectiveWeights(\n agentIds,\n correlationMatrix,\n this.config.correlationThreshold\n );\n\n const { posteriorApproval, posteriorRejection, effectiveVoteCount, downweightedAgents } =\n bayesianAggregate(votes, effectiveWeights);\n\n const decision = determineHigherOrderDecision(posteriorApproval, posteriorRejection);\n const baselineResult = this.aggregateSimpleInternal(votes);\n const improvementOverBaseline = calculateImprovement(\n posteriorApproval,\n posteriorRejection,\n decision,\n baselineResult\n );\n\n const result: HigherOrderVotingResult = {\n decision,\n posteriorApproval,\n posteriorRejection,\n effectiveVoteCount,\n usedCorrelationData: hasSufficientData,\n method: 'ow',\n improvementOverBaseline,\n downweightedAgents,\n reasoning: buildReasoning(decision, effectiveVoteCount, downweightedAgents, 'ow'),\n };\n\n logger.info('OW aggregation complete', {\n decision,\n posteriorApproval: posteriorApproval.toFixed(3),\n effectiveVotes: effectiveVoteCount.toFixed(2),\n downweightedAgents: downweightedAgents.length,\n });\n\n return result;\n }\n\n estimateCorrelation(tracker: ICorrelationTracker): CorrelationMatrix {\n return tracker.computeCorrelationMatrix();\n }\n\n computeISP(\n votes: ReadonlyMap<string, Vote>,\n independentSubsets: readonly IndependentSubset[]\n ): HigherOrderVotingResult {\n if (independentSubsets.length === 0) {\n // Issue #525: Log at INFO level for visibility\n logger.info('No independent subsets, falling back to simple voting', {\n reason: 'no_independent_subsets',\n });\n return this.aggregateSimpleInternal(votes);\n }\n\n const { subsetResults, downweightedAgents } = aggregateSubsets(votes, independentSubsets);\n const { posteriorApproval, posteriorRejection } = combineSubsetResults(subsetResults);\n const effectiveVoteCount = independentSubsets.length;\n const decision = determineHigherOrderDecision(posteriorApproval, posteriorRejection);\n\n const baselineResult = this.aggregateSimpleInternal(votes);\n const improvementOverBaseline = calculateImprovement(\n posteriorApproval,\n posteriorRejection,\n decision,\n baselineResult\n );\n\n const result: HigherOrderVotingResult = {\n decision,\n posteriorApproval,\n posteriorRejection,\n effectiveVoteCount,\n usedCorrelationData: true,\n method: 'isp',\n improvementOverBaseline,\n independentSubsets,\n downweightedAgents,\n reasoning: buildReasoning(decision, effectiveVoteCount, downweightedAgents, 'isp'),\n };\n\n logger.info('ISP aggregation complete', {\n decision,\n subsetCount: independentSubsets.length,\n posteriorApproval: posteriorApproval.toFixed(3),\n });\n\n return result;\n }\n\n aggregate(\n votes: ReadonlyMap<string, Vote>,\n tracker: ICorrelationTracker\n ): HigherOrderVotingResult {\n const agentIds = Array.from(votes.keys());\n\n if (!tracker.hasSufficientData(agentIds)) {\n if (this.config.fallbackToSimpleVoting) {\n // Issue #525: Log at INFO level for visibility\n logger.info('Insufficient data for correlation analysis, using simple voting', {\n agentCount: agentIds.length,\n reason: 'insufficient_tracker_data',\n });\n return this.aggregateSimpleInternal(votes);\n }\n }\n\n const correlationMatrix = tracker.computeCorrelationMatrix();\n const owResult = this.aggregateWithCorrelation(votes, correlationMatrix);\n\n const independentSubsets = tracker.identifyIndependentSubsets();\n if (independentSubsets.length > 1) {\n const ispResult = this.computeISP(votes, independentSubsets);\n const owConfidence = Math.abs(owResult.posteriorApproval - 0.5) * 2;\n const ispConfidence = Math.abs(ispResult.posteriorApproval - 0.5) * 2;\n\n if (ispConfidence > owConfidence) {\n logger.debug('Using ISP result over OW due to higher confidence');\n return ispResult;\n }\n }\n\n return owResult;\n }\n\n getConfig(): HigherOrderVotingConfig {\n return { ...this.config };\n }\n\n private aggregateSimpleInternal(votes: ReadonlyMap<string, Vote>): HigherOrderVotingResult {\n return aggregateSimple(votes, buildReasoning);\n }\n\n private toVotingOutcome(\n votes: Map<string, Vote>,\n result: HigherOrderVotingResult\n ): VotingOutcome {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') approve++;\n else if (vote.decision === 'reject') reject++;\n else abstain++;\n }\n\n const voteCounts: VoteCounts = { approve, reject, abstain, total: votes.size };\n\n const rawPercentage = result.posteriorApproval * 100;\n const approvalPercentage = Number.isFinite(rawPercentage) ? rawPercentage : 0;\n\n return {\n approved: result.decision === 'approve',\n approvalPercentage,\n voteCounts,\n reason: result.reasoning,\n };\n }\n}\n\n/** Creates a new OWVoting instance. */\nexport function createOWVoting(options?: OWVotingOptions): IHigherOrderVoting {\n return new OWVoting(options);\n}\n\n/**\n * Higher-order voting strategy for integration with VotingStrategyFactory.\n * Wraps OWVoting to provide IVotingStrategy interface.\n */\nexport class HigherOrderVotingStrategy extends OWVoting implements IVotingStrategy {\n constructor(options: OWVotingOptions = {}) {\n // #3168: set the algorithm label via the constructor so it survives\n // regardless of how the instance is created (no field-override divergence).\n super({ ...options, algorithm: options.algorithm ?? 'opinion_wise' });\n }\n}\n\n/** Creates a higher-order voting strategy for use with ConsensusEngine. */\nexport function createHigherOrderVotingStrategy(\n options?: OWVotingOptions\n): HigherOrderVotingStrategy {\n return new HigherOrderVotingStrategy(options);\n}\n","/**\n * nexus-agents/consensus - Voting Strategies\n *\n * Implementation of different voting strategies for consensus engine.\n * Supports simple majority, supermajority, unanimous, and proof-of-learning.\n */\n\nimport type {\n ConsensusAlgorithm,\n Vote,\n VoteCounts,\n WeightedVoteCounts,\n AgentPerformance,\n} from './types.js';\nimport { VOTING_THRESHOLDS } from './types.js';\nimport { HigherOrderVotingStrategy } from './higher-order-voting.js';\n\n/**\n * Interface for voting strategy implementations.\n */\nexport interface IVotingStrategy {\n readonly algorithm: ConsensusAlgorithm;\n calculateOutcome(votes: Map<string, Vote>, weights?: Map<string, number>): VotingOutcome;\n}\n\n/**\n * Result of a voting strategy calculation.\n */\nexport interface VotingOutcome {\n approved: boolean;\n approvalPercentage: number;\n voteCounts: VoteCounts;\n weightedCounts?: WeightedVoteCounts;\n reason: string;\n}\n\n/**\n * Evaluates an approval ratio against a threshold — the shared math behind\n * the simple-majority, supermajority and proof-of-learning strategies.\n *\n * `inclusive` selects the comparison: `>=` for supermajority (67% passes at\n * exactly 67%), strict `>` for simple-majority and proof-of-learning (a tie\n * at the threshold is not enough). Callers apply their own zero-denominator\n * guard before calling this.\n */\nfunction evaluateThreshold(\n approveCount: number,\n votingTotal: number,\n threshold: number,\n inclusive: boolean\n): { approved: boolean; approvalPercentage: number } {\n const ratio = approveCount / votingTotal;\n return {\n approved: inclusive ? ratio >= threshold : ratio > threshold,\n approvalPercentage: ratio * 100,\n };\n}\n\n/**\n * Base voting strategy with common functionality.\n */\nabstract class BaseVotingStrategy implements IVotingStrategy {\n abstract readonly algorithm: ConsensusAlgorithm;\n\n abstract calculateOutcome(votes: Map<string, Vote>, weights?: Map<string, number>): VotingOutcome;\n\n /**\n * Count votes by decision type.\n */\n protected countVotes(votes: Map<string, Vote>): VoteCounts {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n\n for (const vote of votes.values()) {\n switch (vote.decision) {\n case 'approve':\n approve++;\n break;\n case 'reject':\n reject++;\n break;\n case 'abstain':\n abstain++;\n break;\n }\n }\n\n return { approve, reject, abstain, total: votes.size };\n }\n\n /**\n * Calculate weighted vote counts using agent performance weights.\n */\n protected countWeightedVotes(\n votes: Map<string, Vote>,\n weights: Map<string, number>\n ): WeightedVoteCounts {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n let totalWeight = 0;\n\n for (const [agentId, vote] of votes.entries()) {\n const weight = weights.get(agentId) ?? 1.0;\n totalWeight += weight;\n\n switch (vote.decision) {\n case 'approve':\n approve += weight;\n break;\n case 'reject':\n reject += weight;\n break;\n case 'abstain':\n abstain += weight;\n break;\n }\n }\n\n return { approve, reject, abstain, totalWeight };\n }\n}\n\n/**\n * Simple majority voting strategy (>50% approval).\n */\nexport class SimpleMajorityStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'simple_majority';\n\n calculateOutcome(votes: Map<string, Vote>): VotingOutcome {\n const counts = this.countVotes(votes);\n const votingVotes = counts.approve + counts.reject; // Abstains don't count\n const threshold = VOTING_THRESHOLDS.simple_majority;\n\n if (votingVotes === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No votes cast (excluding abstentions)',\n };\n }\n\n const { approved, approvalPercentage } = evaluateThreshold(\n counts.approve,\n votingVotes,\n threshold,\n false\n );\n\n return {\n approved,\n approvalPercentage,\n voteCounts: counts,\n reason: approved\n ? `Approved with ${approvalPercentage.toFixed(1)}% (>${String(threshold * 100)}% required)`\n : `Rejected with ${approvalPercentage.toFixed(1)}% (<=${String(threshold * 100)}% threshold)`,\n };\n }\n}\n\n/**\n * Supermajority voting strategy (>=67% approval).\n */\nexport class SupermajorityStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'supermajority';\n\n calculateOutcome(votes: Map<string, Vote>): VotingOutcome {\n const counts = this.countVotes(votes);\n const votingVotes = counts.approve + counts.reject;\n const threshold = VOTING_THRESHOLDS.supermajority;\n\n if (votingVotes === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No votes cast (excluding abstentions)',\n };\n }\n\n const { approved, approvalPercentage } = evaluateThreshold(\n counts.approve,\n votingVotes,\n threshold,\n true\n );\n\n return {\n approved,\n approvalPercentage,\n voteCounts: counts,\n reason: approved\n ? `Approved with ${approvalPercentage.toFixed(1)}% (>=${String(threshold * 100)}% required)`\n : `Rejected with ${approvalPercentage.toFixed(1)}% (<${String(threshold * 100)}% threshold)`,\n };\n }\n}\n\n/**\n * Unanimous voting strategy (100% approval required).\n */\nexport class UnanimousStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'unanimous';\n\n calculateOutcome(votes: Map<string, Vote>): VotingOutcome {\n const counts = this.countVotes(votes);\n\n if (counts.total === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No votes cast',\n };\n }\n\n // For unanimous, any rejection fails the proposal\n // Abstentions are allowed but don't count toward approval\n const approvalPercentage = counts.total > 0 ? (counts.approve / counts.total) * 100 : 0;\n\n if (counts.reject > 0) {\n return {\n approved: false,\n approvalPercentage,\n voteCounts: counts,\n reason: `Rejected: ${String(counts.reject)} rejection(s) cast (unanimous approval required)`,\n };\n }\n\n if (counts.approve === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No approvals cast (at least one approval required)',\n };\n }\n\n return {\n approved: true,\n approvalPercentage,\n voteCounts: counts,\n reason: `Unanimously approved with ${String(counts.approve)} vote(s)`,\n };\n }\n}\n\n/**\n * Proof-of-learning weighted voting strategy.\n * Agents with better track records have more voting power.\n */\nexport class ProofOfLearningStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'proof_of_learning';\n\n calculateOutcome(votes: Map<string, Vote>, weights?: Map<string, number>): VotingOutcome {\n const counts = this.countVotes(votes);\n const effectiveWeights = weights ?? new Map<string, number>();\n const weightedCounts = this.countWeightedVotes(votes, effectiveWeights);\n const threshold = VOTING_THRESHOLDS.proof_of_learning;\n\n const votingWeight = weightedCounts.approve + weightedCounts.reject;\n\n if (votingWeight === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n weightedCounts,\n reason: 'No weighted votes cast (excluding abstentions)',\n };\n }\n\n const { approved, approvalPercentage } = evaluateThreshold(\n weightedCounts.approve,\n votingWeight,\n threshold,\n false\n );\n\n return {\n approved,\n approvalPercentage,\n voteCounts: counts,\n weightedCounts,\n reason: approved\n ? `Approved with ${approvalPercentage.toFixed(1)}% weighted approval`\n : `Rejected with ${approvalPercentage.toFixed(1)}% weighted approval`,\n };\n }\n}\n\n/**\n * Calculate vote weight for an agent based on their performance history.\n * Weight ranges from 0.5 (no history) to 1.0 (perfect track record).\n */\nexport function calculateVoteWeight(performance: AgentPerformance | undefined): number {\n if (performance === undefined || performance.totalVotes === 0) {\n return 1.0; // Default weight for new agents\n }\n\n // Weight = 0.5 + (successRate * 0.5)\n // This gives a range of 0.5 to 1.0 based on historical accuracy\n return 0.5 + performance.successRate * 0.5;\n}\n\n/**\n * Factory for creating voting strategies.\n */\nexport class VotingStrategyFactory {\n private readonly strategies: Map<ConsensusAlgorithm, IVotingStrategy>;\n\n constructor() {\n this.strategies = new Map<ConsensusAlgorithm, IVotingStrategy>([\n ['simple_majority', new SimpleMajorityStrategy()],\n ['supermajority', new SupermajorityStrategy()],\n ['unanimous', new UnanimousStrategy()],\n ['proof_of_learning', new ProofOfLearningStrategy()],\n ['opinion_wise', new HigherOrderVotingStrategy()],\n ['higher_order', new HigherOrderVotingStrategy()],\n ]);\n }\n\n /**\n * Get a voting strategy by algorithm type.\n */\n getStrategy(algorithm: ConsensusAlgorithm): IVotingStrategy {\n const strategy = this.strategies.get(algorithm);\n if (strategy === undefined) {\n throw new Error(`Unknown voting algorithm: ${algorithm}`);\n }\n return strategy;\n }\n\n /**\n * Register a custom voting strategy.\n */\n registerStrategy(strategy: IVotingStrategy): void {\n this.strategies.set(strategy.algorithm, strategy);\n }\n\n /**\n * Get all available algorithm types.\n */\n getAvailableAlgorithms(): ConsensusAlgorithm[] {\n return Array.from(this.strategies.keys());\n }\n}\n\n/**\n * Creates a voting strategy factory with default strategies.\n */\nexport function createStrategyFactory(): VotingStrategyFactory {\n return new VotingStrategyFactory();\n}\n","/**\n * nexus-agents/consensus - Result Builder\n *\n * Helper functions for building consensus results.\n */\n\nimport { getTimeProvider } from '../core/index.js';\nimport type {\n ProposalId,\n ProposalState,\n ConsensusResult,\n ProposalStatus,\n ConsensusEngineConfig,\n} from './types.js';\nimport type { VotingOutcome } from './strategies.js';\n\n/**\n * Build a pending result for an active proposal.\n */\nexport function buildPendingResult(\n state: ProposalState,\n proposalId: ProposalId,\n outcome: VotingOutcome,\n config: ConsensusEngineConfig\n): ConsensusResult {\n const now = new Date(getTimeProvider().now());\n return {\n proposalId,\n proposal: state.proposal,\n outcome: state.status === 'voting' ? 'pending' : state.status,\n votes: new Map(state.votes),\n voteCounts: outcome.voteCounts,\n weightedCounts: outcome.weightedCounts,\n approvalPercentage: outcome.approvalPercentage,\n quorumReached: state.votes.size >= config.minVotersForQuorum,\n startedAt: state.startedAt.toISOString(),\n closedAt: now.toISOString(),\n durationMs: now.getTime() - state.startedAt.getTime(),\n };\n}\n\n/**\n * Build a final result for a closed proposal.\n */\nexport function buildFinalResult(\n state: ProposalState,\n proposalId: ProposalId,\n outcome: VotingOutcome,\n config: ConsensusEngineConfig\n): ConsensusResult {\n const now = new Date(getTimeProvider().now());\n const quorumReached = state.votes.size >= config.minVotersForQuorum;\n const finalStatus = determineFinalStatus(quorumReached, outcome.approved);\n\n return {\n proposalId,\n proposal: state.proposal,\n outcome: finalStatus,\n votes: new Map(state.votes),\n voteCounts: outcome.voteCounts,\n weightedCounts: outcome.weightedCounts,\n approvalPercentage: outcome.approvalPercentage,\n quorumReached,\n startedAt: state.startedAt.toISOString(),\n closedAt: now.toISOString(),\n durationMs: now.getTime() - state.startedAt.getTime(),\n };\n}\n\n/**\n * Build a timeout result for an expired proposal.\n */\nexport function buildTimeoutResult(\n state: ProposalState,\n proposalId: ProposalId,\n outcome: VotingOutcome,\n config: ConsensusEngineConfig\n): ConsensusResult {\n const now = new Date(getTimeProvider().now());\n return {\n proposalId,\n proposal: state.proposal,\n outcome: 'timeout',\n votes: new Map(state.votes),\n voteCounts: outcome.voteCounts,\n weightedCounts: outcome.weightedCounts,\n approvalPercentage: outcome.approvalPercentage,\n quorumReached: state.votes.size >= config.minVotersForQuorum,\n startedAt: state.startedAt.toISOString(),\n closedAt: now.toISOString(),\n durationMs: now.getTime() - state.startedAt.getTime(),\n };\n}\n\n/**\n * Determine final status based on quorum and approval.\n */\nexport function determineFinalStatus(quorumReached: boolean, approved: boolean): ProposalStatus {\n if (!quorumReached || !approved) return 'rejected';\n return 'approved';\n}\n","/**\n * nexus-agents/consensus - Helper Functions\n *\n * Utility functions for the consensus engine.\n */\n\nimport type { ProposalId } from './types.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\n\n/**\n * Generate a unique proposal ID.\n */\nexport function generateProposalId(): ProposalId {\n const timestamp = getTimeProvider().now().toString(36);\n const random = getRandomProvider().random().toString(36).substring(2, 8);\n return `prop_${timestamp}_${random}`;\n}\n","/**\n * nexus-agents/consensus - Incremental Quorum\n *\n * Detects ambiguous voting scenarios and triggers voter pool expansion.\n * Complements agreement-based cascading (early termination when certain)\n * with expansion when uncertain.\n *\n * (Source: Issue #1408 — Incremental Quorum for Consensus Robustness)\n *\n * @module consensus/incremental-quorum\n */\n\nimport type { Vote } from './types.js';\n\n/**\n * Parameters for ambiguity detection.\n */\nexport interface AmbiguityParams {\n /** Minimum average confidence to avoid expansion. */\n readonly confidenceThreshold: number;\n /** If approval rate is within this band of the threshold, consider ambiguous. */\n readonly ambiguityBand: number;\n}\n\n/**\n * Determines if the current voting state is ambiguous.\n *\n * Ambiguity is detected when:\n * 1. Approval rate is within the ambiguity band of the threshold, OR\n * 2. Average voter confidence is below the confidence threshold\n *\n * @param votes - Current vote map\n * @param totalExpected - Total expected voters\n * @param threshold - Algorithm-specific approval threshold (0-1)\n * @param params - Ambiguity detection parameters\n * @returns true if the voting state is ambiguous\n */\nexport function isVotingAmbiguous(\n votes: ReadonlyMap<string, Vote>,\n totalExpected: number,\n threshold: number,\n params: AmbiguityParams\n): boolean {\n if (votes.size === 0) return false;\n\n let approvals = 0;\n let totalConfidence = 0;\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') approvals++;\n totalConfidence += vote.confidence;\n }\n\n const approvalRate = approvals / totalExpected;\n const avgConfidence = totalConfidence / votes.size;\n\n // Check if approval rate is within the ambiguity band of threshold\n const lowerBand = threshold - params.ambiguityBand;\n const upperBand = threshold + params.ambiguityBand;\n const rateAmbiguous = approvalRate >= lowerBand && approvalRate <= upperBand;\n\n // Check if confidence is too low\n const confidenceAmbiguous = avgConfidence < params.confidenceThreshold;\n\n return rateAmbiguous || confidenceAmbiguous;\n}\n","/* eslint-disable max-lines */\n// 426 lines — cohesive single-concern engine. Per governance, 400-600 OK if cohesive.\n\n/**\n * nexus-agents/consensus - Consensus Engine\n *\n * Core consensus engine implementation supporting multiple voting strategies.\n * Manages proposal lifecycle, vote collection, and outcome determination.\n */\n\nimport type { Result, ILogger } from '../core/index.js';\nimport { ok, err, AgentError, createLogger, getTimeProvider } from '../core/index.js';\nimport type {\n Proposal,\n ProposalId,\n Vote,\n ConsensusResult,\n ConsensusAlgorithm,\n AgentPerformance,\n ConsensusEngineConfig,\n ProposalState,\n ConsensusMetrics,\n ProposalCacheConfig,\n IncrementalQuorumConfig,\n VoterExpansionCallback,\n} from './types.js';\nimport {\n ProposalSchema,\n VoteSchema,\n DEFAULT_CONSENSUS_CONFIG,\n VOTING_THRESHOLDS,\n DEFAULT_INCREMENTAL_QUORUM_CONFIG,\n} from './types.js';\nimport { VotingStrategyFactory, calculateVoteWeight, type VotingOutcome } from './strategies.js';\nimport { buildFinalResult, buildTimeoutResult, buildPendingResult } from './result-builder.js';\nimport { generateProposalId } from './helpers.js';\nimport { isVotingAmbiguous } from './incremental-quorum.js';\n\n/**\n * Error class for consensus-related failures.\n */\nexport class ConsensusError extends AgentError {\n constructor(message: string, context?: Record<string, unknown>) {\n super(message, context !== undefined ? { context } : {});\n this.name = 'ConsensusError';\n }\n}\n\n/**\n * Interface for the consensus engine.\n */\nexport interface IConsensusEngine {\n propose(proposal: Proposal): Promise<Result<ProposalId, ConsensusError>>;\n vote(proposalId: ProposalId, agentId: string, vote: Vote): Promise<Result<void, ConsensusError>>;\n getResult(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>>;\n close(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>>;\n getMetrics(): ConsensusMetrics;\n}\n\ninterface InternalMetrics {\n totalProposals: number;\n approvedProposals: number;\n rejectedProposals: number;\n timedOutProposals: number;\n totalDurationMs: number;\n totalVotes: number;\n algorithmUsage: Record<ConsensusAlgorithm, number>;\n}\n\n/**\n * Cache entry for proposal content-based caching (Issue #589).\n */\ninterface ProposalCacheEntry {\n readonly proposalId: ProposalId;\n readonly result: ConsensusResult;\n readonly cachedAt: number;\n}\n\n/**\n * Default proposal cache configuration.\n * Enabled by default to improve determinism (fitness audit recommendation).\n */\n/**\n * Hypothetical-vote stand-ins used by {@link ConsensusEngine.canCascadeEarly}\n * to probe the strategy's outcome under best/worst-case pending votes.\n * The actual `confidence` and `reasoning` fields are never inspected by\n * `IVotingStrategy.calculateOutcome` (all strategies count by `decision`),\n * but must satisfy `VoteSchema` (confidence in [0,1], reasoning non-empty).\n */\nconst HYPOTHETICAL_APPROVE: Vote = {\n decision: 'approve',\n confidence: 0.5,\n reasoning: 'hypothetical-cascade-probe',\n};\nconst HYPOTHETICAL_REJECT: Vote = {\n decision: 'reject',\n confidence: 0.5,\n reasoning: 'hypothetical-cascade-probe',\n};\n\nconst DEFAULT_PROPOSAL_CACHE_CONFIG: ProposalCacheConfig = {\n enabled: true,\n ttlMs: 3600000, // 1 hour\n maxEntries: 500,\n};\n\n/**\n * Consensus engine for multi-agent decision making.\n *\n * @example\n * ```typescript\n * const engine = new ConsensusEngine({ defaultTimeout: 30000 });\n * const proposalResult = await engine.propose({\n * title: 'Use microservices architecture',\n * description: 'Proposal to adopt microservices',\n * algorithm: 'supermajority',\n * });\n * if (proposalResult.ok) {\n * await engine.vote(proposalResult.value, 'agent-1', {\n * decision: 'approve',\n * confidence: 0.9,\n * reasoning: 'Good for scalability',\n * });\n * }\n * ```\n */\nexport class ConsensusEngine implements IConsensusEngine {\n private readonly proposals: Map<ProposalId, ProposalState> = new Map();\n private readonly closedProposals: Map<ProposalId, ConsensusResult> = new Map();\n private readonly agentPerformance: Map<string, AgentPerformance> = new Map();\n private readonly proposalContentCache: Map<string, ProposalCacheEntry> = new Map();\n private readonly strategyFactory: VotingStrategyFactory;\n private readonly config: ConsensusEngineConfig;\n private readonly cacheConfig: ProposalCacheConfig;\n private readonly quorumConfig: IncrementalQuorumConfig;\n private readonly logger: ILogger;\n private readonly metrics: InternalMetrics;\n private voterExpansionCallback?: VoterExpansionCallback;\n\n constructor(config?: Partial<ConsensusEngineConfig>, logger?: ILogger) {\n this.config = { ...DEFAULT_CONSENSUS_CONFIG, ...config };\n this.cacheConfig = { ...DEFAULT_PROPOSAL_CACHE_CONFIG, ...config?.proposalCache };\n this.quorumConfig = { ...DEFAULT_INCREMENTAL_QUORUM_CONFIG, ...config?.incrementalQuorum };\n this.logger = logger ?? createLogger({ component: 'ConsensusEngine' });\n this.strategyFactory = new VotingStrategyFactory();\n this.metrics = this.createInitialMetrics();\n }\n\n /**\n * Sets the callback for incremental quorum voter expansion (Issue #1408).\n * When ambiguous votes are detected, this callback requests additional voters.\n */\n setVoterExpansionCallback(callback: VoterExpansionCallback): void {\n this.voterExpansionCallback = callback;\n }\n\n propose(proposal: Proposal): Promise<Result<ProposalId, ConsensusError>> {\n const validation = ProposalSchema.safeParse(proposal);\n if (!validation.success) {\n return Promise.resolve(\n err(\n new ConsensusError(`Invalid proposal: ${validation.error.message}`, {\n errors: validation.error.issues,\n })\n )\n );\n }\n\n // Check cache for identical proposal content (Issue #589)\n if (this.cacheConfig.enabled) {\n const cachedEntry = this.getCachedResult(validation.data);\n if (cachedEntry !== undefined) {\n this.logger.debug('Returning cached proposal result', {\n cachedProposalId: cachedEntry.proposalId,\n cachedOutcome: cachedEntry.result.outcome,\n });\n return Promise.resolve(ok(cachedEntry.proposalId));\n }\n }\n\n if (this.proposals.size >= this.config.maxActiveProposals) {\n return Promise.resolve(\n err(\n new ConsensusError(\n `Maximum active proposals (${String(this.config.maxActiveProposals)}) reached`\n )\n )\n );\n }\n\n const proposalId = proposal.id ?? generateProposalId();\n const state = this.createProposalState(validation.data, proposalId);\n this.setupTimeout(state, proposalId, proposal.timeout);\n this.registerProposal(proposalId, state, proposal.algorithm);\n return Promise.resolve(ok(proposalId));\n }\n\n async vote(\n proposalId: ProposalId,\n agentId: string,\n vote: Vote\n ): Promise<Result<void, ConsensusError>> {\n const validationErr = this.validateVote(vote);\n if (validationErr !== undefined) return err(validationErr);\n\n const stateErr = this.validateProposalState(proposalId);\n if (stateErr !== undefined) return err(stateErr);\n\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n return err(new ConsensusError(`Proposal ${proposalId} not found`));\n }\n\n this.recordVote(state, agentId, vote);\n\n // Agreement-based cascade always takes priority\n if (this.canCascadeEarly(state)) {\n return this.closeInternal(proposalId).then((r) => (r.ok ? ok(undefined) : err(r.error)));\n }\n\n // All required voters voted — check for incremental quorum expansion\n if (this.allRequiredVotersVoted(state)) {\n // Re-entry guard (#2861): `tryExpandQuorum` awaits its callback and\n // then mutates `state.proposal.requiredVoters` / `expansionRounds`.\n // A concurrent `vote()` that also sees `allRequiredVotersVoted`\n // must NOT start a second expansion — that would invoke the\n // expansion callback twice and clobber the first expansion's\n // voter list. This vote is already recorded; return ok and let\n // the in-flight expansion settle.\n if (state.expansionInFlight === true) {\n return Promise.resolve(ok(undefined));\n }\n state.expansionInFlight = true;\n let expanded: boolean;\n try {\n expanded = await this.tryExpandQuorum(proposalId, state);\n } finally {\n state.expansionInFlight = false;\n }\n if (!expanded) {\n return this.closeInternal(proposalId).then((r) => (r.ok ? ok(undefined) : err(r.error)));\n }\n // Expansion succeeded — wait for new voters\n }\n\n return Promise.resolve(ok(undefined));\n }\n\n getResult(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>> {\n const closedResult = this.closedProposals.get(proposalId);\n if (closedResult !== undefined) return Promise.resolve(ok(closedResult));\n\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n return Promise.resolve(err(new ConsensusError(`Proposal ${proposalId} not found`)));\n }\n\n const outcome = this.calculateOutcome(state);\n return Promise.resolve(ok(buildPendingResult(state, proposalId, outcome, this.config)));\n }\n\n close(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>> {\n return this.closeInternal(proposalId);\n }\n\n getMetrics(): ConsensusMetrics {\n const completed =\n this.metrics.approvedProposals +\n this.metrics.rejectedProposals +\n this.metrics.timedOutProposals;\n return {\n totalProposals: this.metrics.totalProposals,\n approvedProposals: this.metrics.approvedProposals,\n rejectedProposals: this.metrics.rejectedProposals,\n timedOutProposals: this.metrics.timedOutProposals,\n averageDurationMs: completed > 0 ? this.metrics.totalDurationMs / completed : 0,\n averageVotesPerProposal: completed > 0 ? this.metrics.totalVotes / completed : 0,\n algorithmUsage: { ...this.metrics.algorithmUsage },\n };\n }\n\n updateAgentPerformance(agentId: string, wasCorrect: boolean): void {\n const existing = this.agentPerformance.get(agentId);\n const now = getTimeProvider().nowIso();\n\n if (existing === undefined) {\n this.agentPerformance.set(agentId, {\n agentId,\n totalVotes: 1,\n correctVotes: wasCorrect ? 1 : 0,\n successRate: wasCorrect ? 1.0 : 0.0,\n lastUpdated: now,\n });\n } else {\n const totalVotes = existing.totalVotes + 1;\n const correctVotes = existing.correctVotes + (wasCorrect ? 1 : 0);\n this.agentPerformance.set(agentId, {\n agentId,\n totalVotes,\n correctVotes,\n successRate: correctVotes / totalVotes,\n lastUpdated: now,\n });\n }\n }\n\n getAgentPerformance(agentId: string): AgentPerformance | undefined {\n return this.agentPerformance.get(agentId);\n }\n\n getActiveProposalCount(): number {\n return this.proposals.size;\n }\n\n private createProposalState(data: Proposal, proposalId: ProposalId): ProposalState {\n const now = new Date(getTimeProvider().now());\n return {\n proposal: { ...data, id: proposalId, createdAt: now.toISOString() },\n status: 'voting',\n votes: new Map(),\n voteWeights: new Map(),\n startedAt: now,\n };\n }\n\n private setupTimeout(state: ProposalState, proposalId: ProposalId, timeout?: number): void {\n const timeoutMs = timeout ?? this.config.defaultTimeout;\n state.timeoutId = setTimeout(() => {\n this.handleTimeout(proposalId);\n }, timeoutMs);\n }\n\n private registerProposal(\n proposalId: ProposalId,\n state: ProposalState,\n algorithm: ConsensusAlgorithm\n ): void {\n this.proposals.set(proposalId, state);\n this.metrics.totalProposals++;\n this.metrics.algorithmUsage[algorithm]++;\n this.logger.info('Proposal created', {\n proposalId,\n title: state.proposal.title,\n algorithm,\n timeout: this.config.defaultTimeout,\n });\n }\n\n private validateVote(vote: Vote): ConsensusError | undefined {\n const validation = VoteSchema.safeParse(vote);\n if (!validation.success) {\n return new ConsensusError(`Invalid vote: ${validation.error.message}`, {\n errors: validation.error.issues,\n });\n }\n return undefined;\n }\n\n private validateProposalState(proposalId: ProposalId): ConsensusError | undefined {\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n if (this.closedProposals.has(proposalId)) {\n return new ConsensusError(`Proposal ${proposalId} is already closed`);\n }\n return new ConsensusError(`Proposal ${proposalId} not found`);\n }\n if (state.status !== 'voting') {\n return new ConsensusError(`Proposal ${proposalId} is not accepting votes`, {\n status: state.status,\n });\n }\n return undefined;\n }\n\n private recordVote(state: ProposalState, agentId: string, vote: Vote): void {\n state.votes.set(agentId, {\n ...vote,\n timestamp: getTimeProvider().nowIso(),\n });\n if (state.proposal.algorithm === 'proof_of_learning') {\n const performance = this.agentPerformance.get(agentId);\n state.voteWeights.set(agentId, calculateVoteWeight(performance));\n }\n this.logger.debug('Vote recorded', {\n proposalId: state.proposal.id,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n });\n }\n\n private closeInternal(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>> {\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n const closed = this.closedProposals.get(proposalId);\n if (closed !== undefined) return Promise.resolve(ok(closed));\n return Promise.resolve(err(new ConsensusError(`Proposal ${proposalId} not found`)));\n }\n\n if (state.timeoutId !== undefined) clearTimeout(state.timeoutId);\n\n const outcome = this.calculateOutcome(state);\n const result = buildFinalResult(state, proposalId, outcome, this.config);\n this.finalize(proposalId, result, state.votes.size);\n return Promise.resolve(ok(result));\n }\n\n private handleTimeout(proposalId: ProposalId): void {\n const state = this.proposals.get(proposalId);\n if (state?.status !== 'voting') return;\n\n this.logger.warn('Proposal timed out', { proposalId, voteCount: state.votes.size });\n const outcome = this.calculateOutcome(state);\n const result = buildTimeoutResult(state, proposalId, outcome, this.config);\n this.proposals.delete(proposalId);\n this.addClosedProposal(proposalId, result);\n this.metrics.timedOutProposals++;\n this.metrics.totalDurationMs += result.durationMs;\n this.metrics.totalVotes += state.votes.size;\n }\n\n private finalize(proposalId: ProposalId, result: ConsensusResult, voteCount: number): void {\n this.proposals.delete(proposalId);\n this.addClosedProposal(proposalId, result);\n this.updateMetrics(result);\n\n // Cache successful results for determinism (Issue #589)\n if (\n this.cacheConfig.enabled &&\n (result.outcome === 'approved' || result.outcome === 'rejected')\n ) {\n this.addToCache(result.proposal, proposalId, result);\n }\n\n this.logger.info('Proposal closed', {\n proposalId,\n outcome: result.outcome,\n approvalPercentage: result.approvalPercentage.toFixed(1),\n voteCount,\n quorumReached: result.quorumReached,\n durationMs: result.durationMs,\n });\n }\n\n /**\n * Adds a closed proposal and evicts oldest entries if over limit.\n * Issue #549: Prevent unbounded memory growth in closedProposals Map.\n */\n private addClosedProposal(proposalId: ProposalId, result: ConsensusResult): void {\n // Evict oldest entries if at capacity (Map maintains insertion order)\n while (this.closedProposals.size >= this.config.maxClosedProposals) {\n const firstKey = this.closedProposals.keys().next();\n if (firstKey.done === true) break;\n const oldestKey = firstKey.value;\n this.closedProposals.delete(oldestKey);\n this.logger.debug('Evicted oldest closed proposal', { evictedId: oldestKey });\n }\n this.closedProposals.set(proposalId, result);\n }\n\n private calculateOutcome(state: ProposalState): VotingOutcome {\n const strategy = this.strategyFactory.getStrategy(state.proposal.algorithm);\n const outcome: VotingOutcome = strategy.calculateOutcome(state.votes, state.voteWeights);\n return outcome;\n }\n\n /**\n * Agreement-based cascading: close early when outcome is mathematically determined.\n *\n * #2822: the prior implementation computed approval rates against\n * `totalExpected = requiredVoters.length` and compared against\n * `VOTING_THRESHOLDS[algorithm]` directly. Every voting strategy\n * (`SimpleMajorityStrategy`, `SupermajorityStrategy`, `UnanimousStrategy`,\n * `ProofOfLearningStrategy`) uses `approve + reject` as its denominator —\n * abstains are explicitly excluded. The two diverged whenever abstains\n * were present, producing wrong-winner cascades (e.g. 5-voter supermajority\n * with [approve, abstain, abstain, abstain, pending] cascade-rejected even\n * though the strategy would approve at close).\n *\n * The fix delegates to the strategy itself: build a best-case (all pending\n * voters approve) and worst-case (all pending voters reject) hypothetical\n * vote map, call `strategy.calculateOutcome` on each, and cascade only\n * when both extremes yield the same outcome. This guarantees parity with\n * the strategy's denominator semantics by construction.\n */\n private canCascadeEarly(state: ProposalState): boolean {\n const required = state.proposal.requiredVoters;\n if (required === undefined || required.length === 0) return false;\n if (state.votes.size === 0) return false;\n\n const pending = required.filter((voter) => !state.votes.has(voter));\n if (pending.length === 0) return false; // All voted — handled by allRequiredVotersVoted\n\n const strategy = this.strategyFactory.getStrategy(state.proposal.algorithm);\n\n const bestCase = new Map<string, Vote>(state.votes);\n const worstCase = new Map<string, Vote>(state.votes);\n for (const voter of pending) {\n bestCase.set(voter, HYPOTHETICAL_APPROVE);\n worstCase.set(voter, HYPOTHETICAL_REJECT);\n }\n\n const bestOutcome = strategy.calculateOutcome(bestCase, state.voteWeights);\n const worstOutcome = strategy.calculateOutcome(worstCase, state.voteWeights);\n\n if (bestOutcome.approved !== worstOutcome.approved) return false;\n\n this.logger.info('Agreement cascade: outcome determined', {\n proposalId: state.proposal.id,\n outcome: bestOutcome.approved ? 'approve' : 'reject',\n votesCast: state.votes.size,\n pending: pending.length,\n algorithm: state.proposal.algorithm,\n });\n return true;\n }\n\n private allRequiredVotersVoted(state: ProposalState): boolean {\n const required = state.proposal.requiredVoters;\n if (required === undefined || required.length === 0) return false;\n return required.every((voterId) => state.votes.has(voterId));\n }\n\n /**\n * Attempts incremental quorum expansion when voting is ambiguous (Issue #1408).\n * Returns true if expansion occurred (wait for new voters), false to close immediately.\n */\n private async tryExpandQuorum(proposalId: ProposalId, state: ProposalState): Promise<boolean> {\n if (!this.quorumConfig.enabled) return false;\n if (this.voterExpansionCallback === undefined) return false;\n\n const rounds = state.expansionRounds ?? 0;\n if (rounds >= this.quorumConfig.maxExpansionRounds) return false;\n\n const required = state.proposal.requiredVoters;\n if (required === undefined) return false;\n\n const threshold = VOTING_THRESHOLDS[state.proposal.algorithm];\n const ambiguous = isVotingAmbiguous(state.votes, required.length, threshold, {\n confidenceThreshold: this.quorumConfig.confidenceThreshold,\n ambiguityBand: this.quorumConfig.ambiguityBand,\n });\n\n if (!ambiguous) return false;\n\n let newVoters: readonly string[];\n try {\n newVoters = await this.voterExpansionCallback(\n proposalId,\n required.length,\n this.quorumConfig.votersPerExpansion\n );\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n this.logger.warn('Incremental quorum: expansion callback threw; closing as-is', {\n proposalId,\n errorMessage: error.message,\n });\n return false;\n }\n\n if (newVoters.length === 0) {\n this.logger.info('Incremental quorum: no additional voters available', { proposalId });\n return false;\n }\n\n // Expand the required voters list\n state.proposal.requiredVoters = [...required, ...newVoters];\n state.expansionRounds = rounds + 1;\n\n this.logger.info('Incremental quorum: expanded voter pool', {\n proposalId,\n round: rounds + 1,\n newVoters: newVoters.length,\n totalVoters: state.proposal.requiredVoters.length,\n });\n\n return true;\n }\n\n private updateMetrics(result: ConsensusResult): void {\n this.metrics.totalDurationMs += result.durationMs;\n this.metrics.totalVotes += result.voteCounts.total;\n if (result.outcome === 'approved') this.metrics.approvedProposals++;\n else if (result.outcome === 'rejected') this.metrics.rejectedProposals++;\n else if (result.outcome === 'timeout') this.metrics.timedOutProposals++;\n }\n\n private createInitialMetrics(): InternalMetrics {\n return {\n totalProposals: 0,\n approvedProposals: 0,\n rejectedProposals: 0,\n timedOutProposals: 0,\n totalDurationMs: 0,\n totalVotes: 0,\n algorithmUsage: {\n simple_majority: 0,\n supermajority: 0,\n unanimous: 0,\n proof_of_learning: 0,\n opinion_wise: 0,\n higher_order: 0,\n },\n };\n }\n\n // ============================================================================\n // Proposal Content Caching (Issue #589)\n // ============================================================================\n\n /**\n * Creates a content hash for a proposal to enable cache lookups.\n * Hash is based on title, description, and algorithm (deterministic content).\n */\n private hashProposalContent(proposal: Proposal): string {\n const content = [proposal.title, proposal.description, proposal.algorithm].join('|');\n // Simple FNV-1a hash for fast deterministic hashing\n let hash = 2166136261;\n for (let i = 0; i < content.length; i++) {\n hash ^= content.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0).toString(16);\n }\n\n /**\n * Gets cached result for a proposal if it exists and hasn't expired.\n */\n private getCachedResult(proposal: Proposal): ProposalCacheEntry | undefined {\n const hash = this.hashProposalContent(proposal);\n const cached = this.proposalContentCache.get(hash);\n if (cached === undefined) return undefined;\n\n const now = getTimeProvider().now();\n if (now - cached.cachedAt > this.cacheConfig.ttlMs) {\n this.proposalContentCache.delete(hash);\n this.logger.debug('Cache entry expired', { hash });\n return undefined;\n }\n\n return cached;\n }\n\n /**\n * Adds a proposal result to the cache, evicting oldest entries if needed.\n */\n private addToCache(proposal: Proposal, proposalId: ProposalId, result: ConsensusResult): void {\n const hash = this.hashProposalContent(proposal);\n\n // Evict oldest entries if at capacity (Map maintains insertion order)\n while (this.proposalContentCache.size >= this.cacheConfig.maxEntries) {\n const firstKey = this.proposalContentCache.keys().next();\n if (firstKey.done === true) break;\n const oldestKey = firstKey.value;\n this.proposalContentCache.delete(oldestKey);\n this.logger.debug('Evicted oldest cache entry', { hash: oldestKey });\n }\n\n this.proposalContentCache.set(hash, {\n proposalId,\n result,\n cachedAt: getTimeProvider().now(),\n });\n this.logger.debug('Added proposal to cache', { hash, proposalId });\n }\n\n /**\n * Gets the current cache size (for testing/monitoring).\n */\n getCacheSize(): number {\n return this.proposalContentCache.size;\n }\n\n /**\n * Clears the proposal content cache (for testing/reset).\n */\n clearCache(): void {\n this.proposalContentCache.clear();\n this.logger.debug('Proposal cache cleared');\n }\n}\n\n/**\n * Create a consensus engine with the given configuration.\n *\n * @example\n * ```typescript\n * const engine = createConsensusEngine({\n * defaultTimeout: 60000,\n * maxActiveProposals: 10,\n * });\n * ```\n */\nexport function createConsensusEngine(\n config?: Partial<ConsensusEngineConfig>,\n logger?: ILogger\n): ConsensusEngine {\n return new ConsensusEngine(config, logger);\n}\n","/**\n * Unified Quorum Validator\n *\n * Abstracts quorum validation across VotingProtocol, WeightedVoting, and ConsensusEngine.\n * Per redundancy-analysis.md Section 3.4 - consolidates three quorum implementations.\n *\n * @module consensus/quorum-validator\n * (Source: Issue #576, ADR-0003)\n */\n\nimport { createLogger, formatPercentage, type ILogger } from '../core/index.js';\nimport type { ConsensusAlgorithm, Vote, VoteCounts, WeightedVoteCounts } from './types-core.js';\nimport { SUPERMAJORITY_THRESHOLD } from './types-core.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Agent record for eligibility checks and Byzantine detection.\n */\nexport interface AgentRecord {\n readonly agentId: string;\n readonly weight: number;\n readonly trustScore: number;\n readonly byzantineFlags?: number;\n readonly successRate?: number;\n readonly totalTasks?: number;\n}\n\n/**\n * Quorum validation configuration.\n */\nexport interface QuorumValidationConfig {\n /** Algorithm type */\n readonly algorithm: ConsensusAlgorithm | 'weighted_byzantine';\n /** Numeric threshold (0-1 for percentage, 0-N for weighted sum) */\n readonly threshold: number;\n /** Minimum voters required */\n readonly minVoters: number;\n /** Enable Byzantine detection */\n readonly enableByzantineDetection?: boolean;\n /** Apply confidence multiplier to weights */\n readonly confidenceMultiplier?: boolean;\n /** Include abstentions in quorum calculation */\n readonly includeAbstentions?: boolean;\n}\n\n/**\n * Input for quorum validation.\n */\nexport interface QuorumValidationInput {\n /** Votes cast by agent ID */\n readonly votes: ReadonlyMap<string, Vote>;\n /** Optional: Pre-calculated agent weights */\n readonly agentWeights?: ReadonlyMap<string, number>;\n /** Configuration */\n readonly config: QuorumValidationConfig;\n /** Optional: Agent records for eligibility checks */\n readonly agentRecords?: ReadonlyMap<string, AgentRecord>;\n /** Optional: Required participant count (for ratio-based quorum) */\n readonly requiredParticipants?: number;\n}\n\n/**\n * Quorum validation result (discriminated union).\n */\nexport type QuorumValidationResult =\n | {\n readonly status: 'reached';\n readonly decision: 'approve' | 'reject';\n readonly confidence: number;\n readonly reasoning: string;\n }\n | {\n readonly status: 'not_reached';\n readonly reason: 'insufficient_votes' | 'insufficient_weight' | 'no_consensus';\n readonly details: string;\n }\n | { readonly status: 'invalid'; readonly error: string }\n | { readonly status: 'timeout'; readonly partial: boolean; readonly details: string };\n\n/**\n * Detailed quorum breakdown for observability.\n */\nexport interface QuorumBreakdown {\n readonly totalVotes: number;\n readonly voteCounts: VoteCounts;\n readonly totalWeight: number | undefined;\n readonly weightedCounts: WeightedVoteCounts | undefined;\n readonly threshold: number;\n readonly actualQuorum: number;\n readonly quorumReached: boolean;\n readonly eligibleAgents: readonly string[];\n readonly reasoning: string;\n}\n\n/**\n * Eligibility check result.\n */\nexport type EligibilityResult =\n | { readonly eligible: true; readonly weight: number }\n | {\n readonly eligible: false;\n readonly reason: 'insufficient_weight' | 'low_trust' | 'byzantine_flagged' | 'excluded';\n readonly weight: number;\n };\n\n/**\n * Unified quorum validator interface.\n */\nexport interface IQuorumValidator {\n validateQuorum(input: QuorumValidationInput): QuorumValidationResult;\n getQuorumBreakdown(input: QuorumValidationInput): QuorumBreakdown;\n isAgentEligible(\n agentId: string,\n record: AgentRecord | undefined,\n config: QuorumValidationConfig\n ): EligibilityResult;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Default quorum thresholds by algorithm type.\n * Used for reference when config.threshold is not specified.\n */\nexport const DEFAULT_QUORUM_THRESHOLDS: Readonly<\n Record<ConsensusAlgorithm | 'weighted_byzantine', number>\n> = {\n simple_majority: 0.5,\n supermajority: SUPERMAJORITY_THRESHOLD,\n unanimous: 1.0,\n proof_of_learning: 0.5,\n opinion_wise: 0.5,\n higher_order: 0.5,\n // Byzantine fault tolerance also requires 2/3 — the same supermajority.\n weighted_byzantine: SUPERMAJORITY_THRESHOLD,\n};\n\nconst DEFAULT_MIN_TRUST = 0.3;\nconst DEFAULT_MIN_WEIGHT = 0.1;\n\n/**\n * Unified quorum validator implementation.\n */\nexport class QuorumValidator implements IQuorumValidator {\n private readonly logger: ILogger;\n\n constructor(logger?: ILogger) {\n this.logger = logger ?? createLogger({ component: 'QuorumValidator' });\n }\n\n validateQuorum(input: QuorumValidationInput): QuorumValidationResult {\n const { votes, config } = input;\n\n // Validate input\n if (votes.size === 0) {\n return { status: 'invalid', error: 'No votes provided' };\n }\n\n // Calculate breakdown\n const breakdown = this.getQuorumBreakdown(input);\n\n // Check if quorum reached\n if (!breakdown.quorumReached) {\n return this.buildNotReachedResult(breakdown, config);\n }\n\n // Determine decision\n return this.buildReachedResult(breakdown);\n }\n\n getQuorumBreakdown(input: QuorumValidationInput): QuorumBreakdown {\n const { votes, agentWeights, config, agentRecords, requiredParticipants } = input;\n\n // Count votes\n const voteCounts = this.countVotes(votes);\n const eligibleAgents = this.getEligibleAgents(votes, agentRecords, config);\n\n // Calculate weights if applicable\n const { totalWeight, weightedCounts } = this.calculateWeights(\n votes,\n agentWeights,\n agentRecords,\n config\n );\n\n // Calculate quorum based on algorithm\n const { threshold, actualQuorum, quorumReached, reasoning } = this.calculateQuorumStatus(\n voteCounts,\n weightedCounts,\n totalWeight,\n config,\n requiredParticipants ?? votes.size\n );\n\n return {\n totalVotes: votes.size,\n voteCounts,\n totalWeight,\n weightedCounts,\n threshold,\n actualQuorum,\n quorumReached,\n eligibleAgents,\n reasoning,\n };\n }\n\n isAgentEligible(\n agentId: string,\n record: AgentRecord | undefined,\n config: QuorumValidationConfig\n ): EligibilityResult {\n if (record === undefined) {\n return { eligible: true, weight: 1.0 }; // Default eligibility\n }\n\n // Check Byzantine flags\n if (config.enableByzantineDetection === true && (record.byzantineFlags ?? 0) > 0) {\n this.logger.debug('Agent flagged as Byzantine', { agentId, flags: record.byzantineFlags });\n return { eligible: false, reason: 'byzantine_flagged', weight: record.weight };\n }\n\n // Check trust score\n if (record.trustScore < DEFAULT_MIN_TRUST) {\n this.logger.debug('Agent trust score below threshold', {\n agentId,\n trustScore: record.trustScore,\n });\n return { eligible: false, reason: 'low_trust', weight: record.weight };\n }\n\n // Check weight\n if (record.weight < DEFAULT_MIN_WEIGHT) {\n this.logger.debug('Agent weight below threshold', { agentId, weight: record.weight });\n return { eligible: false, reason: 'insufficient_weight', weight: record.weight };\n }\n\n return { eligible: true, weight: record.weight };\n }\n\n private countVotes(votes: ReadonlyMap<string, Vote>): VoteCounts {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n\n for (const vote of votes.values()) {\n switch (vote.decision) {\n case 'approve':\n approve++;\n break;\n case 'reject':\n reject++;\n break;\n case 'abstain':\n abstain++;\n break;\n }\n }\n\n return { approve, reject, abstain, total: votes.size };\n }\n\n private getEligibleAgents(\n votes: ReadonlyMap<string, Vote>,\n agentRecords: ReadonlyMap<string, AgentRecord> | undefined,\n config: QuorumValidationConfig\n ): readonly string[] {\n const eligible: string[] = [];\n\n for (const agentId of votes.keys()) {\n const record = agentRecords?.get(agentId);\n const result = this.isAgentEligible(agentId, record, config);\n if (result.eligible) {\n eligible.push(agentId);\n }\n }\n\n return eligible;\n }\n\n private calculateWeights(\n votes: ReadonlyMap<string, Vote>,\n agentWeights: ReadonlyMap<string, number> | undefined,\n agentRecords: ReadonlyMap<string, AgentRecord> | undefined,\n config: QuorumValidationConfig\n ): { totalWeight: number | undefined; weightedCounts: WeightedVoteCounts | undefined } {\n // Skip weight calculation for simple algorithms\n if (config.algorithm === 'simple_majority' || config.algorithm === 'unanimous') {\n return { totalWeight: undefined, weightedCounts: undefined };\n }\n\n const counts = { totalWeight: 0, approve: 0, reject: 0, abstain: 0 };\n\n for (const [agentId, vote] of votes.entries()) {\n const weight = this.getVoteWeight(agentId, vote, agentWeights, agentRecords, config);\n counts.totalWeight += weight;\n this.addWeightToDecision(counts, vote.decision, weight);\n }\n\n return {\n totalWeight: counts.totalWeight,\n weightedCounts: {\n approve: counts.approve,\n reject: counts.reject,\n abstain: counts.abstain,\n totalWeight: counts.totalWeight,\n },\n };\n }\n\n private getVoteWeight(\n agentId: string,\n vote: Vote,\n agentWeights: ReadonlyMap<string, number> | undefined,\n agentRecords: ReadonlyMap<string, AgentRecord> | undefined,\n config: QuorumValidationConfig\n ): number {\n let weight = agentWeights?.get(agentId) ?? agentRecords?.get(agentId)?.weight ?? 1.0;\n if (config.confidenceMultiplier === true) {\n weight *= vote.confidence;\n }\n return weight;\n }\n\n private addWeightToDecision(\n counts: { approve: number; reject: number; abstain: number },\n decision: 'approve' | 'reject' | 'abstain',\n weight: number\n ): void {\n counts[decision] += weight;\n }\n\n private calculateQuorumStatus(\n voteCounts: VoteCounts,\n weightedCounts: WeightedVoteCounts | undefined,\n totalWeight: number | undefined,\n config: QuorumValidationConfig,\n requiredParticipants: number\n ): { threshold: number; actualQuorum: number; quorumReached: boolean; reasoning: string } {\n const threshold = config.threshold;\n\n // For weighted algorithms, use weighted counts\n if (weightedCounts !== undefined && totalWeight !== undefined && totalWeight > 0) {\n return this.calculateWeightedQuorum(weightedCounts, totalWeight, threshold);\n }\n\n // For simple algorithms, use vote counts\n return this.calculateSimpleQuorum(voteCounts, requiredParticipants, threshold, config);\n }\n\n private calculateWeightedQuorum(\n weightedCounts: WeightedVoteCounts,\n totalWeight: number,\n threshold: number\n ): { threshold: number; actualQuorum: number; quorumReached: boolean; reasoning: string } {\n const quorumReached = totalWeight >= threshold;\n const approveRatio = weightedCounts.approve / totalWeight;\n const rejectRatio = weightedCounts.reject / totalWeight;\n\n const reasoning = this.buildWeightedReasoning(\n quorumReached,\n totalWeight,\n threshold,\n approveRatio,\n rejectRatio\n );\n\n return { threshold, actualQuorum: totalWeight, quorumReached, reasoning };\n }\n\n private buildWeightedReasoning(\n quorumReached: boolean,\n totalWeight: number,\n threshold: number,\n approveRatio: number,\n rejectRatio: number\n ): string {\n if (!quorumReached) {\n return `Weighted quorum not reached: ${totalWeight.toFixed(2)} < ${String(threshold)}`;\n }\n if (approveRatio > rejectRatio) {\n return `Approval wins with weighted ratio ${formatPercentage(approveRatio, 1)}`;\n }\n if (rejectRatio > approveRatio) {\n return `Rejection wins with weighted ratio ${formatPercentage(rejectRatio, 1)}`;\n }\n return `No clear winner: approve=${formatPercentage(approveRatio, 1)}, reject=${formatPercentage(rejectRatio, 1)}`;\n }\n\n private calculateSimpleQuorum(\n voteCounts: VoteCounts,\n requiredParticipants: number,\n threshold: number,\n config: QuorumValidationConfig\n ): { threshold: number; actualQuorum: number; quorumReached: boolean; reasoning: string } {\n const activeVotes =\n config.includeAbstentions === true\n ? voteCounts.total\n : voteCounts.approve + voteCounts.reject;\n\n const total = requiredParticipants > 0 ? requiredParticipants : activeVotes;\n const approveRatio = total > 0 ? voteCounts.approve / total : 0;\n const rejectRatio = total > 0 ? voteCounts.reject / total : 0;\n\n const hasMinVoters = activeVotes >= config.minVoters;\n const quorumReached = hasMinVoters && (approveRatio >= threshold || rejectRatio >= threshold);\n\n const reasoning = this.buildSimpleReasoning({\n hasMinVoters,\n activeVotes,\n minVoters: config.minVoters,\n approveRatio,\n rejectRatio,\n threshold,\n });\n\n return {\n threshold,\n actualQuorum: Math.max(approveRatio, rejectRatio),\n quorumReached,\n reasoning,\n };\n }\n\n private buildSimpleReasoning(params: {\n hasMinVoters: boolean;\n activeVotes: number;\n minVoters: number;\n approveRatio: number;\n rejectRatio: number;\n threshold: number;\n }): string {\n const { hasMinVoters, activeVotes, minVoters, approveRatio, rejectRatio, threshold } = params;\n if (!hasMinVoters) {\n return `Insufficient voters: ${String(activeVotes)} < ${String(minVoters)}`;\n }\n if (approveRatio >= threshold) {\n return `Approval reaches threshold: ${formatPercentage(approveRatio, 1)} >= ${formatPercentage(threshold, 1)}`;\n }\n if (rejectRatio >= threshold) {\n return `Rejection reaches threshold: ${formatPercentage(rejectRatio, 1)} >= ${formatPercentage(threshold, 1)}`;\n }\n return `No decision reached threshold: approve=${formatPercentage(approveRatio, 1)}, reject=${formatPercentage(rejectRatio, 1)}`;\n }\n\n private buildNotReachedResult(\n breakdown: QuorumBreakdown,\n config: QuorumValidationConfig\n ): QuorumValidationResult {\n const { voteCounts, weightedCounts, threshold } = breakdown;\n\n if (voteCounts.total < config.minVoters) {\n return {\n status: 'not_reached',\n reason: 'insufficient_votes',\n details: `Only ${String(voteCounts.total)} votes, need ${String(config.minVoters)}`,\n };\n }\n\n if (weightedCounts !== undefined && weightedCounts.totalWeight < threshold) {\n return {\n status: 'not_reached',\n reason: 'insufficient_weight',\n details: `Weight ${weightedCounts.totalWeight.toFixed(2)} < threshold ${String(threshold)}`,\n };\n }\n\n return {\n status: 'not_reached',\n reason: 'no_consensus',\n details: breakdown.reasoning,\n };\n }\n\n private buildReachedResult(breakdown: QuorumBreakdown): QuorumValidationResult {\n const { voteCounts, weightedCounts } = breakdown;\n\n // Determine winning decision\n const approves = weightedCounts?.approve ?? voteCounts.approve;\n const rejects = weightedCounts?.reject ?? voteCounts.reject;\n const total = weightedCounts?.totalWeight ?? voteCounts.total;\n\n const decision: 'approve' | 'reject' = approves >= rejects ? 'approve' : 'reject';\n const confidence = total > 0 ? Math.abs(approves - rejects) / total : 0;\n\n return {\n status: 'reached',\n decision,\n confidence,\n reasoning: breakdown.reasoning,\n };\n }\n}\n\n/**\n * Creates a quorum validator instance.\n */\nexport function createQuorumValidator(logger?: ILogger): IQuorumValidator {\n return new QuorumValidator(logger);\n}\n","/**\n * Helper functions for the multi-round voting protocol.\n *\n * @module consensus/voting-protocol-helpers\n * (Source: Issue #100, arXiv:2512.21352)\n */\n\nimport type {\n VotingSession,\n VotingRound,\n VotingRoundPhase,\n VotingProtocolConfig,\n VotingProtocolResult,\n AgentFinding,\n Vote,\n ConsolidatedFinding,\n RoundSummary,\n SycophancyReport,\n SycophancyIndicator,\n} from './types.js';\nimport { createQuorumValidator, type QuorumValidationConfig } from './quorum-validator.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\n\n/**\n * Generate a unique session ID.\n */\nexport function generateSessionId(): string {\n const time = getTimeProvider();\n const random = getRandomProvider();\n return `session_${String(time.now())}_${random.randomString(7)}`;\n}\n\n/**\n * Generate a unique finding ID.\n */\nexport function generateFindingId(): string {\n const time = getTimeProvider();\n const random = getRandomProvider();\n return `finding_${String(time.now())}_${random.randomString(7)}`;\n}\n\n/**\n * Generate a unique round ID.\n */\nexport function generateRoundId(): string {\n const time = getTimeProvider();\n const random = getRandomProvider();\n return `round_${String(time.now())}_${random.randomString(7)}`;\n}\n\n/**\n * Create a new voting round.\n */\nexport function createRound(phase: VotingRoundPhase, roundNumber: number): VotingRound {\n const time = getTimeProvider();\n return {\n id: generateRoundId(),\n phase,\n status: 'in_progress',\n findings: new Map(),\n findingVotes: new Map(),\n finalVotes: new Map(),\n startedAt: time.nowIso(),\n roundNumber,\n };\n}\n\n/**\n * Find the most common element in an array.\n */\nexport function mostCommon<T>(items: T[]): T | undefined {\n if (items.length === 0) return undefined;\n\n const counts = new Map<T, number>();\n items.forEach((item) => {\n counts.set(item, (counts.get(item) ?? 0) + 1);\n });\n\n let maxCount = 0;\n let result: T | undefined;\n counts.forEach((count, item) => {\n if (count > maxCount) {\n maxCount = count;\n result = item;\n }\n });\n\n return result;\n}\n\n/**\n * Calculate agreement score from votes.\n */\nexport function calculateAgreementScore(votes: Vote[]): number {\n if (votes.length < 2) return 1;\n\n const decisions = votes.map((v) => v.decision);\n const mostCommonDecision = mostCommon(decisions);\n const agreementCount = decisions.filter((d) => d === mostCommonDecision).length;\n\n return agreementCount / votes.length;\n}\n\n/**\n * Determine outcome from final votes using unified QuorumValidator.\n * Per ADR-0003, this delegates to the consolidated quorum logic.\n */\nexport function determineOutcome(\n votes: Vote[],\n config: VotingProtocolConfig\n): VotingProtocolResult['outcome'] {\n if (votes.length === 0) return 'no_consensus';\n\n // Convert array to Map for QuorumValidator\n const voteMap = new Map<string, Vote>();\n votes.forEach((vote, index) => {\n voteMap.set(`voter_${String(index)}`, vote);\n });\n\n // Create quorum config from voting protocol config\n const quorumConfig: QuorumValidationConfig = {\n algorithm: 'simple_majority',\n threshold: config.agreementThreshold,\n minVoters: 2, // Minimum for valid consensus\n };\n\n // Use unified QuorumValidator\n const validator = createQuorumValidator();\n const result = validator.validateQuorum({\n votes: voteMap,\n config: quorumConfig,\n });\n\n // Map QuorumValidationResult to VotingProtocolResult outcome\n if (result.status === 'reached') {\n return result.decision === 'approve' ? 'approved' : 'rejected';\n }\n\n // Check for mixed votes (needs revision)\n const approvals = votes.filter((v) => v.decision === 'approve').length;\n const rejections = votes.filter((v) => v.decision === 'reject').length;\n if (approvals > 0 && rejections > 0) return 'needs_revision';\n\n return 'no_consensus';\n}\n\n/**\n * Consolidate findings from deliberation round.\n */\nexport function consolidateFindings(session: VotingSession): ConsolidatedFinding[] {\n const deliberationRound = session.rounds[1];\n if (!deliberationRound) return [];\n\n const consolidated: ConsolidatedFinding[] = [];\n\n deliberationRound.findings.forEach((finding, findingId) => {\n const votes = deliberationRound.findingVotes.get(findingId) ?? [];\n const agreeVotes = votes.filter((v) => v.agree);\n const agreementRatio = votes.length > 0 ? agreeVotes.length / votes.length : 0;\n\n // Only include findings with some agreement\n if (agreementRatio >= 0.5) {\n // Determine final severity (use most common amended severity or original)\n const severityVotes = agreeVotes\n .filter((v) => v.amendedSeverity)\n .map((v) => v.amendedSeverity);\n const finalSeverity =\n severityVotes.length > 0\n ? (mostCommon(severityVotes) ?? finding.severity)\n : finding.severity;\n\n const consolidatedFinding: ConsolidatedFinding = {\n id: findingId,\n category: finding.category,\n severity: finalSeverity,\n description: finding.description,\n supportingAgents: agreeVotes.map((v) => v.agentId),\n agreementRatio,\n originalFindings: [finding],\n };\n if (finding.location !== undefined) {\n consolidatedFinding.location = finding.location;\n }\n if (finding.suggestion !== undefined) {\n consolidatedFinding.suggestion = finding.suggestion;\n }\n consolidated.push(consolidatedFinding);\n }\n });\n\n // Sort by severity and agreement\n return consolidated.sort((a, b) => {\n const severityOrder = { critical: 0, major: 1, minor: 2, suggestion: 3 };\n const sevDiff = severityOrder[a.severity] - severityOrder[b.severity];\n if (sevDiff !== 0) return sevDiff;\n return b.agreementRatio - a.agreementRatio;\n });\n}\n\n/**\n * Build round summaries from session.\n */\nexport function buildRoundSummaries(session: VotingSession): RoundSummary[] {\n const time = getTimeProvider();\n return session.rounds.map((round, index) => {\n const startTime = new Date(round.startedAt).getTime();\n const endTime =\n round.completedAt !== undefined ? new Date(round.completedAt).getTime() : time.now();\n\n let votesCount = 0;\n let agreementScore = 0;\n\n if (round.phase === 'deliberation') {\n // Count finding votes\n round.findingVotes.forEach((votes) => {\n votesCount += votes.length;\n const agreeCount = votes.filter((v) => v.agree).length;\n agreementScore += votes.length > 0 ? agreeCount / votes.length : 0;\n });\n const findingsCount = round.findingVotes.size;\n if (findingsCount > 0) {\n agreementScore /= findingsCount;\n }\n } else if (round.phase === 'consensus') {\n // Count final votes\n votesCount = round.finalVotes.size;\n const votes = Array.from(round.finalVotes.values());\n agreementScore = calculateAgreementScore(votes);\n }\n\n return {\n roundNumber: index + 1,\n phase: round.phase,\n findingsCount: round.findings.size,\n votesCount,\n agreementScore,\n durationMs: endTime - startTime,\n };\n });\n}\n\n// ============================================================================\n// Sycophancy Detection\n// ============================================================================\n\n/**\n * Check for premature consensus pattern.\n */\nexport function checkPrematureConsensus(session: VotingSession): SycophancyIndicator | null {\n const analysisRound = session.rounds[0];\n if (!analysisRound) return null;\n\n const agentFindings = new Map<string, AgentFinding[]>();\n analysisRound.findings.forEach((finding) => {\n const existing = agentFindings.get(finding.agentId) ?? [];\n existing.push(finding);\n agentFindings.set(finding.agentId, existing);\n });\n\n const allConfidences: number[] = [];\n analysisRound.findings.forEach((finding) => {\n allConfidences.push(finding.confidence);\n });\n\n const avgConfidence =\n allConfidences.length > 0\n ? allConfidences.reduce((a, b) => a + b, 0) / allConfidences.length\n : 0;\n\n if (avgConfidence > 0.95 && agentFindings.size >= 2) {\n return {\n type: 'premature_consensus',\n description: 'All agents showing unusually high confidence',\n severity: 'medium',\n agents: Array.from(agentFindings.keys()),\n };\n }\n\n return null;\n}\n\n/**\n * Check for opinion convergence pattern.\n */\nexport function checkOpinionConvergence(session: VotingSession): SycophancyIndicator | null {\n const deliberationRound = session.rounds[1];\n if (!deliberationRound) return null;\n\n let totalVotes = 0;\n let agreeVotes = 0;\n\n deliberationRound.findingVotes.forEach((votes) => {\n totalVotes += votes.length;\n agreeVotes += votes.filter((v) => v.agree).length;\n });\n\n const agreeRatio = totalVotes > 0 ? agreeVotes / totalVotes : 0;\n\n if (agreeRatio > session.config.sycophancyThreshold && totalVotes > 3) {\n const affectedAgents: string[] = [];\n deliberationRound.findingVotes.forEach((votes) => {\n votes.forEach((v) => {\n if (v.agree && !affectedAgents.includes(v.agentId)) {\n affectedAgents.push(v.agentId);\n }\n });\n });\n\n return {\n type: 'opinion_convergence',\n description: `${String(Math.round(agreeRatio * 100))}% agreement rate suggests possible opinion convergence`,\n severity: 'high',\n agents: affectedAgents,\n };\n }\n\n return null;\n}\n\n/**\n * Check for confidence inflation pattern.\n */\nexport function checkConfidenceInflation(session: VotingSession): SycophancyIndicator | null {\n const consensusRound = session.rounds[2];\n if (!consensusRound) return null;\n\n const votes = Array.from(consensusRound.finalVotes.values());\n if (votes.length < 2) return null;\n\n const confidences = votes.map((v) => v.confidence);\n const avgConfidence = confidences.reduce((a, b) => a + b, 0) / confidences.length;\n const allHigh = confidences.every((c) => c > 0.9);\n\n if (allHigh && avgConfidence > 0.95) {\n return {\n type: 'confidence_inflation',\n description: 'All agents reporting very high confidence suggests possible sycophancy',\n severity: 'medium',\n agents: Array.from(consensusRound.finalVotes.keys()),\n };\n }\n\n return null;\n}\n\n/**\n * Run all sycophancy detection checks.\n */\nexport function detectSycophancyPatterns(session: VotingSession): SycophancyReport {\n const indicators: SycophancyIndicator[] = [];\n const affectedAgents: string[] = [];\n\n const prematureConsensus = checkPrematureConsensus(session);\n if (prematureConsensus) {\n indicators.push(prematureConsensus);\n affectedAgents.push(...prematureConsensus.agents);\n }\n\n const opinionConvergence = checkOpinionConvergence(session);\n if (opinionConvergence) {\n indicators.push(opinionConvergence);\n affectedAgents.push(...opinionConvergence.agents);\n }\n\n const confidenceInflation = checkConfidenceInflation(session);\n if (confidenceInflation) {\n indicators.push(confidenceInflation);\n affectedAgents.push(...confidenceInflation.agents);\n }\n\n const detected = indicators.length > 0;\n const confidenceScore = Math.min(1, indicators.length * 0.3);\n const uniqueAffected = [...new Set(affectedAgents)];\n\n return {\n detected,\n confidenceScore,\n indicators,\n affectedAgents: uniqueAffected,\n recommendation: detected\n ? 'Consider requesting independent re-analysis or adding more diverse agents'\n : 'No sycophancy detected',\n };\n}\n","/**\n * Multi-Round Voting Protocol Implementation\n *\n * Implements a structured 3-round voting protocol for multi-agent code review\n * based on research showing 91.7-100% success rates vs 78% single-agent baseline.\n *\n * @module consensus/voting-protocol\n * (Source: Issue #100, arXiv:2512.21352 - Multi-Agent Committees)\n * (Source: arXiv:2509.23055 - Sycophancy Prevention)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type { ILogger } from '../core/index.js';\nimport type {\n IVotingProtocol,\n VotingSession,\n VotingRound,\n VotingProtocolConfig,\n VotingProtocolResult,\n AgentFinding,\n FindingVote,\n Vote,\n SycophancyReport,\n} from './types.js';\nimport {\n AgentFindingSchema,\n FindingVoteSchema,\n VoteSchema,\n DEFAULT_VOTING_PROTOCOL_CONFIG,\n} from './types.js';\nimport {\n generateSessionId,\n generateFindingId,\n createRound,\n consolidateFindings,\n buildRoundSummaries,\n determineOutcome,\n calculateAgreementScore,\n detectSycophancyPatterns,\n} from './voting-protocol-helpers.js';\n\nconst logger: ILogger = createLogger({ component: 'voting-protocol' });\n\n/**\n * Multi-round voting protocol for code review.\n */\nexport class VotingProtocol implements IVotingProtocol {\n private readonly sessions: Map<string, VotingSession> = new Map();\n private readonly logger: ILogger;\n\n constructor(customLogger?: ILogger) {\n this.logger = customLogger ?? logger;\n }\n\n /**\n * Create a new voting session with a committee.\n */\n createSession(\n topic: string,\n committee: string[],\n config?: Partial<VotingProtocolConfig>\n ): VotingSession {\n const sessionConfig = { ...DEFAULT_VOTING_PROTOCOL_CONFIG, ...config };\n\n if (committee.length < 2) {\n throw new Error('Committee must have at least 2 members');\n }\n\n if (committee.length > sessionConfig.committeeSize) {\n throw new Error(`Committee size exceeds maximum (${String(sessionConfig.committeeSize)})`);\n }\n\n const session: VotingSession = {\n id: generateSessionId(),\n topic,\n committee,\n rounds: [],\n currentRound: 0,\n config: sessionConfig,\n status: 'active',\n createdAt: getTimeProvider().nowIso(),\n };\n\n this.sessions.set(session.id, session);\n this.logger.info('Voting session created', {\n sessionId: session.id,\n topic,\n committeeSize: committee.length,\n });\n\n return session;\n }\n\n /**\n * Start the analysis round (Round 1).\n */\n startAnalysisRound(sessionId: string): Promise<VotingRound> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n if (session.currentRound !== 0) {\n return Promise.reject(new Error('Analysis round can only be started as Round 1'));\n }\n\n const round = createRound('analysis', 1);\n session.rounds.push(round);\n session.currentRound = 1;\n\n this.logger.info('Analysis round started', { sessionId, roundId: round.id });\n return Promise.resolve(round);\n }\n\n /**\n * Submit findings from an agent during analysis.\n */\n submitFindings(sessionId: string, agentId: string, findings: AgentFinding[]): Promise<void> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n const currentRound = this.getCurrentRound(session);\n if (currentRound.phase !== 'analysis') {\n return Promise.reject(new Error('Findings can only be submitted during analysis round'));\n }\n\n if (!session.committee.includes(agentId)) {\n return Promise.reject(new Error(`Agent ${agentId} is not a committee member`));\n }\n\n for (const finding of findings) {\n const validation = AgentFindingSchema.safeParse(finding);\n if (!validation.success) {\n return Promise.reject(new Error(`Invalid finding: ${validation.error.message}`));\n }\n\n const findingId = generateFindingId();\n const timestampedFinding = {\n ...validation.data,\n agentId,\n timestamp: getTimeProvider().nowIso(),\n };\n currentRound.findings.set(findingId, timestampedFinding);\n }\n\n this.logger.debug('Findings submitted', { sessionId, agentId, findingsCount: findings.length });\n return Promise.resolve();\n }\n\n /**\n * Start the deliberation round (Round 2).\n */\n startDeliberationRound(sessionId: string): Promise<VotingRound> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n if (session.currentRound !== 1) {\n return Promise.reject(new Error('Deliberation round can only be started after analysis'));\n }\n\n const analysisRound = session.rounds[0];\n if (analysisRound) {\n analysisRound.status = 'completed';\n analysisRound.completedAt = getTimeProvider().nowIso();\n }\n\n if (session.config.enableAntiSycophancy) {\n const report = this.detectSycophancy(sessionId);\n if (report.detected) {\n this.logger.warn('Sycophancy detected before deliberation', {\n sessionId,\n indicators: report.indicators.length,\n });\n }\n }\n\n const round = createRound('deliberation', 2);\n if (analysisRound) {\n analysisRound.findings.forEach((finding, id) => {\n round.findings.set(id, finding);\n round.findingVotes.set(id, []);\n });\n }\n\n session.rounds.push(round);\n session.currentRound = 2;\n\n this.logger.info('Deliberation round started', {\n sessionId,\n roundId: round.id,\n findingsCount: round.findings.size,\n });\n return Promise.resolve(round);\n }\n\n /**\n * Vote on findings during deliberation.\n */\n voteOnFinding(sessionId: string, vote: FindingVote): Promise<void> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n const currentRound = this.getCurrentRound(session);\n if (currentRound.phase !== 'deliberation') {\n return Promise.reject(new Error('Finding votes can only be submitted during deliberation'));\n }\n\n const validation = FindingVoteSchema.safeParse(vote);\n if (!validation.success) {\n return Promise.reject(new Error(`Invalid vote: ${validation.error.message}`));\n }\n\n if (!session.committee.includes(vote.agentId)) {\n return Promise.reject(new Error(`Agent ${vote.agentId} is not a committee member`));\n }\n\n if (!currentRound.findings.has(vote.findingId)) {\n return Promise.reject(new Error(`Finding ${vote.findingId} not found`));\n }\n\n const existingVotes = currentRound.findingVotes.get(vote.findingId) ?? [];\n const filtered = existingVotes.filter((v) => v.agentId !== vote.agentId);\n filtered.push(validation.data);\n currentRound.findingVotes.set(vote.findingId, filtered);\n\n this.logger.debug('Finding vote recorded', {\n sessionId,\n agentId: vote.agentId,\n findingId: vote.findingId,\n agree: vote.agree,\n });\n return Promise.resolve();\n }\n\n /**\n * Start the consensus round (Round 3).\n */\n startConsensusRound(sessionId: string): Promise<VotingRound> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n if (session.currentRound !== 2) {\n return Promise.reject(new Error('Consensus round can only be started after deliberation'));\n }\n\n const deliberationRound = session.rounds[1];\n if (deliberationRound) {\n deliberationRound.status = 'completed';\n deliberationRound.completedAt = getTimeProvider().nowIso();\n }\n\n const round = createRound('consensus', 3);\n session.rounds.push(round);\n session.currentRound = 3;\n\n this.logger.info('Consensus round started', { sessionId, roundId: round.id });\n return Promise.resolve(round);\n }\n\n /**\n * Submit final vote during consensus.\n */\n submitFinalVote(sessionId: string, agentId: string, vote: Vote): Promise<void> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n const currentRound = this.getCurrentRound(session);\n if (currentRound.phase !== 'consensus') {\n return Promise.reject(new Error('Final votes can only be submitted during consensus'));\n }\n\n const validation = VoteSchema.safeParse(vote);\n if (!validation.success) {\n return Promise.reject(new Error(`Invalid vote: ${validation.error.message}`));\n }\n\n if (!session.committee.includes(agentId)) {\n return Promise.reject(new Error(`Agent ${agentId} is not a committee member`));\n }\n\n currentRound.finalVotes.set(agentId, {\n ...validation.data,\n timestamp: getTimeProvider().nowIso(),\n });\n\n this.logger.debug('Final vote recorded', {\n sessionId,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n });\n return Promise.resolve();\n }\n\n /**\n * Get the final result.\n */\n getResult(sessionId: string): Promise<VotingProtocolResult | null> {\n const session = this.sessions.get(sessionId);\n if (!session) return Promise.resolve(null);\n\n if (session.status === 'completed' && session.finalResult) {\n return Promise.resolve(session.finalResult);\n }\n\n if (session.currentRound < 3) return Promise.resolve(null);\n\n const consensusRound = session.rounds[2];\n if (!consensusRound) return Promise.resolve(null);\n\n const allVoted = session.committee.every((agentId) => consensusRound.finalVotes.has(agentId));\n if (!allVoted) return Promise.resolve(null);\n\n const result = this.buildFinalResult(session);\n session.finalResult = result;\n session.status = 'completed';\n session.completedAt = getTimeProvider().nowIso();\n\n consensusRound.status = 'completed';\n consensusRound.completedAt = getTimeProvider().nowIso();\n\n this.logger.info('Voting session completed', {\n sessionId,\n outcome: result.outcome,\n agreementScore: result.agreementScore,\n consolidatedFindings: result.consolidatedFindings.length,\n });\n\n return Promise.resolve(result);\n }\n\n /**\n * Detect sycophancy patterns.\n */\n detectSycophancy(sessionId: string): SycophancyReport {\n const session = this.getSessionOrThrow(sessionId);\n return detectSycophancyPatterns(session);\n }\n\n /**\n * Get the current session state.\n */\n getSession(sessionId: string): VotingSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n private getSessionOrThrow(sessionId: string): VotingSession {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session ${sessionId} not found`);\n }\n return session;\n }\n\n private validateSessionActive(session: VotingSession): void {\n if (session.status !== 'active') {\n throw new Error(`Session ${session.id} is ${session.status}`);\n }\n }\n\n private getCurrentRound(session: VotingSession): VotingRound {\n const round = session.rounds[session.currentRound - 1];\n if (!round) {\n throw new Error(`No round ${String(session.currentRound)} found`);\n }\n return round;\n }\n\n private buildFinalResult(session: VotingSession): VotingProtocolResult {\n const startTime = new Date(session.createdAt).getTime();\n const endTime = getTimeProvider().now();\n\n const consolidatedFindingsList = consolidateFindings(session);\n const roundSummaries = buildRoundSummaries(session);\n\n const consensusRound = session.rounds[2];\n const finalVotes = consensusRound ? Array.from(consensusRound.finalVotes.values()) : [];\n const outcome = determineOutcome(finalVotes, session.config);\n const agreementScore = calculateAgreementScore(finalVotes);\n const sycophancyReport = detectSycophancyPatterns(session);\n\n return {\n sessionId: session.id,\n topic: session.topic,\n outcome,\n consolidatedFindings: consolidatedFindingsList,\n roundSummaries,\n agreementScore,\n sycophancyDetected: sycophancyReport.detected,\n totalDurationMs: endTime - startTime,\n participatingAgents: session.committee,\n };\n }\n}\n\n/**\n * Create a voting protocol instance.\n */\nexport function createVotingProtocol(customLogger?: ILogger): VotingProtocol {\n return new VotingProtocol(customLogger);\n}\n","/**\n * Byzantine Detection EventBus Integration Helpers\n * (Source: Issue #218, Sprint #228)\n *\n * Provides helper functions for emitting Byzantine fault detection events.\n * Used by CP-WBFT weighted voting to report Byzantine behavior patterns.\n *\n * @module agents/collaboration/byzantine-events\n */\n\nimport type {\n IEventBus,\n ByzantineWeightUpdatedEvent,\n ByzantinePatternDetectedEvent,\n ByzantineAgentFlaggedEvent,\n ByzantineCollusionSuspectedEvent,\n} from './event-bus-types.js';\nimport { createEvent } from './event-bus.js';\n\n// =============================================================================\n// Weight Update Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.weight_updated event. */\nexport interface WeightUpdatedParams {\n readonly agentId: string;\n readonly previousWeight: number;\n readonly newWeight: number;\n readonly reason: 'performance_update' | 'flag_penalty' | 'recalibration';\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.weight_updated event when an agent's weight changes. */\nexport function emitWeightUpdated(eventBus: IEventBus, params: WeightUpdatedParams): void {\n const event = createEvent<ByzantineWeightUpdatedEvent>(\n 'byzantine.weight_updated',\n {\n agentId: params.agentId,\n previousWeight: params.previousWeight,\n newWeight: params.newWeight,\n reason: params.reason,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n\n// =============================================================================\n// Pattern Detection Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.pattern_detected event. */\nexport interface PatternDetectedParams {\n readonly patternType: 'contrarian' | 'collusion';\n readonly agentIds: readonly string[];\n readonly confidence: number;\n readonly details: string;\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.pattern_detected event when Byzantine pattern is detected. */\nexport function emitPatternDetected(eventBus: IEventBus, params: PatternDetectedParams): void {\n const event = createEvent<ByzantinePatternDetectedEvent>(\n 'byzantine.pattern_detected',\n {\n patternType: params.patternType,\n agentIds: params.agentIds,\n confidence: params.confidence,\n details: params.details,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n\n// =============================================================================\n// Agent Flagged Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.agent_flagged event. */\nexport interface AgentFlaggedParams {\n readonly agentId: string;\n readonly reason: string;\n readonly previousWeight: number;\n readonly canVote: boolean;\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.agent_flagged event when an agent is flagged as Byzantine. */\nexport function emitAgentFlagged(eventBus: IEventBus, params: AgentFlaggedParams): void {\n const event = createEvent<ByzantineAgentFlaggedEvent>(\n 'byzantine.agent_flagged',\n {\n agentId: params.agentId,\n reason: params.reason,\n previousWeight: params.previousWeight,\n canVote: params.canVote,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n\n// =============================================================================\n// Collusion Suspected Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.collusion_suspected event. */\nexport interface CollusionSuspectedParams {\n readonly groupAgentIds: readonly string[];\n readonly groupSize: number;\n readonly votingBlock: number;\n readonly threshold: number;\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.collusion_suspected event when collusion pattern is suspected. */\nexport function emitCollusionSuspected(\n eventBus: IEventBus,\n params: CollusionSuspectedParams\n): void {\n const event = createEvent<ByzantineCollusionSuspectedEvent>(\n 'byzantine.collusion_suspected',\n {\n groupAgentIds: params.groupAgentIds,\n groupSize: params.groupSize,\n votingBlock: params.votingBlock,\n threshold: params.threshold,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n","/**\n * nexus-agents/consensus - Weighted Byzantine Voting Helpers\n *\n * Pure helper functions extracted from WeightedVoting class.\n * These functions are stateless and operate on parameters only.\n *\n * @module consensus/weighted-voting-helpers\n * (Source: Issue #103, arXiv:2511.10400 - CP-WBFT)\n */\n\nimport { getTimeProvider } from '../core/index.js';\nimport { clamp01 } from '../utils/math-utils.js';\nimport type { WeightedAgentRecord, WeightedConsensusResult, Vote } from './types.js';\nimport type { IEventBus } from '../core/event-bus.js';\n\n/**\n * Mutable agent record for internal tracking.\n * Used internally by WeightedVoting class.\n */\nexport interface MutableAgentRecord {\n agentId: string;\n totalTasks: number;\n successfulTasks: number;\n failedTasks: number;\n partialTasks: number;\n successRate: number;\n weight: number;\n trustScore: number;\n byzantineFlags: number;\n byzantineReasons: string[];\n lastActive: Date;\n createdAt: Date;\n}\n\n/** Options for WeightedVoting constructor. */\nexport interface WeightedVotingOptions {\n /** Configuration for voting thresholds and weights. */\n config?: Partial<import('./types.js').WeightedVotingConfig>;\n /** Optional event bus for Byzantine detection events (Issue #218). */\n eventBus?: IEventBus;\n /** Whether to emit Byzantine detection events (default: true if eventBus provided). */\n emitEvents?: boolean;\n}\n\n/**\n * Check if a vote is a low-confidence contrarian vote.\n * Used for Byzantine pattern detection.\n */\nexport function isLowConfidenceContrarian(vote: Vote, majorityApprove: boolean): boolean {\n const isContrarian = majorityApprove ? vote.decision === 'reject' : vote.decision === 'approve';\n return isContrarian && vote.confidence < 0.3;\n}\n\n/**\n * Compute the majority vote direction based on weighted votes.\n * Returns true if majority approves, false if majority rejects.\n */\nexport function computeMajorityDirection(\n voteArray: ReadonlyArray<readonly [string, Vote]>,\n weights: ReadonlyMap<string, number>\n): boolean {\n let totalApprove = 0;\n let totalReject = 0;\n for (const [agentId, vote] of voteArray) {\n const w = weights.get(agentId) ?? 0;\n if (vote.decision === 'approve') totalApprove += w;\n if (vote.decision === 'reject') totalReject += w;\n }\n return totalApprove > totalReject;\n}\n\n/**\n * Determine consensus decision based on vote tallies.\n */\nexport function determineDecision(\n approval: number,\n rejection: number,\n total: number,\n quorumReached: boolean,\n quorumThreshold: number\n): WeightedConsensusResult['decision'] {\n if (!quorumReached || total === 0) return 'no_consensus';\n const approvalRatio = approval / total;\n const rejectionRatio = rejection / total;\n if (approvalRatio > rejectionRatio && approvalRatio >= quorumThreshold) return 'approve';\n if (rejectionRatio > approvalRatio && rejectionRatio >= quorumThreshold) return 'reject';\n return 'no_consensus';\n}\n\n/**\n * Update derived metrics (success rate, trust score) on a mutable record.\n */\nexport function updateDerivedMetrics(record: MutableAgentRecord): void {\n // Update success rate\n if (record.totalTasks > 0) {\n const weightedSuccess = record.successfulTasks + record.partialTasks * 0.5;\n record.successRate = weightedSuccess / record.totalTasks;\n }\n\n // Update trust score based on weight and Byzantine flags\n const byzantinePenalty = Math.pow(0.7, record.byzantineFlags);\n record.trustScore = Math.min(1, record.weight * byzantinePenalty);\n}\n\n/**\n * Convert a mutable internal record to an immutable public record.\n */\nexport function toImmutableRecord(record: MutableAgentRecord): WeightedAgentRecord {\n return {\n agentId: record.agentId,\n totalTasks: record.totalTasks,\n successfulTasks: record.successfulTasks,\n failedTasks: record.failedTasks,\n partialTasks: record.partialTasks,\n successRate: record.successRate,\n weight: record.weight,\n trustScore: record.trustScore,\n byzantineFlags: record.byzantineFlags,\n lastActive: record.lastActive,\n createdAt: record.createdAt,\n };\n}\n\n/**\n * Create a vote signature for collusion detection.\n * Combines decision and confidence into a unique key.\n */\nexport function createVoteSignature(vote: Vote): string {\n return `${vote.decision}:${vote.confidence.toFixed(2)}`;\n}\n\n/**\n * Group votes by their signature for collusion pattern detection.\n */\nexport function groupVotesBySignature(\n voteArray: ReadonlyArray<readonly [string, Vote]>\n): Map<string, string[]> {\n const signatures = new Map<string, string[]>();\n for (const [agentId, vote] of voteArray) {\n const sig = createVoteSignature(vote);\n const agents = signatures.get(sig) ?? [];\n agents.push(agentId);\n signatures.set(sig, agents);\n }\n return signatures;\n}\n\n/**\n * Create a new mutable agent record with initial values.\n */\nexport function createAgentRecord(agentId: string, initialWeight: number): MutableAgentRecord {\n const now = new Date(getTimeProvider().now());\n return {\n agentId,\n totalTasks: 0,\n successfulTasks: 0,\n failedTasks: 0,\n partialTasks: 0,\n successRate: 0,\n weight: initialWeight,\n trustScore: initialWeight,\n byzantineFlags: 0,\n byzantineReasons: [],\n lastActive: now,\n createdAt: now,\n };\n}\n\n/**\n * Compute global success statistics from all agent records.\n */\nexport function computeGlobalStats(records: Iterable<MutableAgentRecord>): {\n globalSuccessRate: number;\n totalTasks: number;\n} {\n let totalSuccess = 0;\n let totalTasks = 0;\n\n for (const record of records) {\n totalSuccess += record.successfulTasks;\n totalTasks += record.totalTasks;\n }\n\n const globalSuccessRate = totalTasks > 0 ? totalSuccess / totalTasks : 0.5;\n return { globalSuccessRate, totalTasks };\n}\n\n/**\n * Calculate calibrated weight based on relative performance.\n */\nexport function calculateCalibratedWeight(\n record: MutableAgentRecord,\n globalSuccessRate: number,\n initialWeight: number\n): number {\n const relativePerformance = record.successRate / Math.max(0.01, globalSuccessRate);\n const calibratedWeight = clamp01(initialWeight * relativePerformance);\n // Smooth transition (50% old weight, 50% calibrated)\n return (record.weight + calibratedWeight) / 2;\n}\n\n/**\n * Apply weight change based on task outcome.\n */\nexport function applyOutcomeWeight(\n currentWeight: number,\n outcome: import('./types.js').TaskOutcomeStatus,\n decayFactor: number,\n recoveryFactor: number\n): number {\n switch (outcome) {\n case 'success':\n return Math.min(1, currentWeight * recoveryFactor);\n case 'failure':\n return Math.max(0, currentWeight * decayFactor);\n case 'partial':\n return Math.max(0, currentWeight * ((decayFactor + 1) / 2));\n case 'unknown':\n return currentWeight;\n }\n}\n","/**\n * nexus-agents/consensus - Weighted Byzantine Voting Implementation\n *\n * Implements CP-WBFT (arXiv:2511.10400) for weighted Byzantine fault-tolerant voting.\n * Agent votes are weighted by historical reliability with automatic trust calibration.\n *\n * @module consensus/weighted-voting\n * (Source: Issue #103, arXiv:2511.10400 - CP-WBFT)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type {\n IWeightedVoting,\n WeightedAgentRecord,\n WeightedConsensusResult,\n WeightedVotingConfig,\n TaskOutcomeStatus,\n Vote,\n} from './types.js';\nimport { DEFAULT_WEIGHTED_VOTING_CONFIG } from './types.js';\nimport type { IEventBus } from '../core/event-bus.js';\nimport {\n emitWeightUpdated,\n emitPatternDetected,\n emitAgentFlagged,\n emitCollusionSuspected,\n} from '../agents/collaboration/byzantine-events.js';\nimport {\n type MutableAgentRecord,\n type WeightedVotingOptions,\n isLowConfidenceContrarian,\n computeMajorityDirection,\n determineDecision,\n updateDerivedMetrics,\n toImmutableRecord,\n groupVotesBySignature,\n createAgentRecord,\n computeGlobalStats,\n calculateCalibratedWeight,\n applyOutcomeWeight,\n} from './weighted-voting-helpers.js';\n\nexport type { WeightedVotingOptions } from './weighted-voting-helpers.js';\n\nconst logger = createLogger({ component: 'weighted-voting' });\n\n/**\n * Weighted Byzantine voting implementation.\n * Implements CP-WBFT pattern for fault-tolerant multi-agent consensus.\n */\nexport class WeightedVoting implements IWeightedVoting {\n private readonly records: Map<string, MutableAgentRecord> = new Map();\n private readonly config: WeightedVotingConfig;\n private readonly eventBus: IEventBus | undefined;\n private readonly emitEvents: boolean;\n\n constructor(options: WeightedVotingOptions = {}) {\n this.config = { ...DEFAULT_WEIGHTED_VOTING_CONFIG, ...options.config };\n this.eventBus = options.eventBus ?? undefined;\n this.emitEvents = options.emitEvents ?? options.eventBus !== undefined;\n logger.info('WeightedVoting initialized', {\n config: this.config,\n eventsEnabled: this.emitEvents,\n });\n }\n\n calculateWeight(agentId: string): number {\n const record = this.records.get(agentId);\n if (record === undefined) return 0;\n return record.weight;\n }\n\n updatePerformance(agentId: string, outcome: TaskOutcomeStatus): void {\n let record = this.records.get(agentId);\n if (record === undefined) {\n this.registerAgent(agentId);\n record = this.records.get(agentId);\n if (record === undefined) return;\n }\n\n const previousWeight = record.weight;\n record.totalTasks += 1;\n record.lastActive = new Date(getTimeProvider().now());\n\n // Update task counts\n if (outcome === 'success') record.successfulTasks += 1;\n else if (outcome === 'failure') record.failedTasks += 1;\n else if (outcome === 'partial') record.partialTasks += 1;\n\n // Apply weight change\n record.weight = applyOutcomeWeight(\n record.weight,\n outcome,\n this.config.weightDecayFactor,\n this.config.weightRecoveryFactor\n );\n updateDerivedMetrics(record);\n this.emitWeightChange(agentId, previousWeight, record.weight, 'performance_update');\n\n logger.debug('Performance updated', {\n agentId,\n outcome,\n newWeight: record.weight,\n successRate: record.successRate,\n });\n }\n\n weightedConsensus(votes: ReadonlyMap<string, Vote>): WeightedConsensusResult {\n const { approval, rejection, total, agents, breakdown } = this.countVotes(votes);\n const byzantineDetected = this.detectByzantinePatterns(votes, breakdown);\n const quorumReached = total >= this.config.quorumThreshold;\n const decision = determineDecision(\n approval,\n rejection,\n total,\n quorumReached,\n this.config.quorumThreshold\n );\n\n const result: WeightedConsensusResult = {\n decision,\n weightedApproval: approval,\n weightedRejection: rejection,\n totalWeight: total,\n quorumReached,\n byzantineDetected,\n participatingAgents: agents,\n weightBreakdown: breakdown,\n };\n\n this.logConsensusResult(result);\n return result;\n }\n\n registerAgent(agentId: string): void {\n if (this.records.has(agentId)) {\n logger.debug('Agent already registered', { agentId });\n return;\n }\n const record = createAgentRecord(agentId, this.config.initialWeight);\n this.records.set(agentId, record);\n logger.info('Agent registered', { agentId, initialWeight: this.config.initialWeight });\n }\n\n getAgentRecord(agentId: string): WeightedAgentRecord | undefined {\n const record = this.records.get(agentId);\n if (record === undefined) return undefined;\n return toImmutableRecord(record);\n }\n\n flagByzantine(agentId: string, reason: string): void {\n const record = this.records.get(agentId);\n if (record === undefined) {\n logger.warn('Cannot flag unregistered agent', { agentId });\n return;\n }\n\n const previousWeight = record.weight;\n record.byzantineFlags += 1;\n record.byzantineReasons.push(reason);\n record.weight = Math.max(0, record.weight * 0.5);\n updateDerivedMetrics(record);\n\n const canStillVote = this.canVote(agentId);\n this.emitAgentFlaggedEvent(agentId, reason, previousWeight, canStillVote);\n this.emitWeightChange(agentId, previousWeight, record.weight, 'flag_penalty');\n\n logger.warn('Agent flagged for Byzantine behavior', {\n agentId,\n reason,\n totalFlags: record.byzantineFlags,\n newWeight: record.weight,\n });\n\n if (record.byzantineFlags >= this.config.byzantineFlagThreshold) {\n this.excludeAgent(record);\n }\n }\n\n getAllRecords(): readonly WeightedAgentRecord[] {\n return Array.from(this.records.values()).map((r) => toImmutableRecord(r));\n }\n\n canVote(agentId: string): boolean {\n const record = this.records.get(agentId);\n if (record === undefined) return false;\n return record.weight >= this.config.minWeight && record.trustScore >= this.config.minTrustScore;\n }\n\n recalibrateWeights(): void {\n const { globalSuccessRate, totalTasks } = computeGlobalStats(this.records.values());\n if (totalTasks === 0) return;\n\n for (const record of this.records.values()) {\n if (record.totalTasks < 3) continue;\n const previousWeight = record.weight;\n record.weight = calculateCalibratedWeight(\n record,\n globalSuccessRate,\n this.config.initialWeight\n );\n updateDerivedMetrics(record);\n this.emitWeightChange(record.agentId, previousWeight, record.weight, 'recalibration');\n }\n\n logger.info('Weights recalibrated', {\n agentCount: this.records.size,\n globalSuccessRate: globalSuccessRate.toFixed(3),\n });\n }\n\n // Private helpers\n\n private countVotes(votes: ReadonlyMap<string, Vote>): {\n approval: number;\n rejection: number;\n total: number;\n agents: string[];\n breakdown: Map<string, number>;\n } {\n let approval = 0;\n let rejection = 0;\n let total = 0;\n const agents: string[] = [];\n const breakdown = new Map<string, number>();\n\n for (const [agentId, vote] of votes) {\n if (!this.canVote(agentId)) {\n logger.warn('Agent cannot vote', { agentId, reason: 'insufficient weight or trust' });\n continue;\n }\n const weight = this.calculateWeight(agentId);\n breakdown.set(agentId, weight);\n agents.push(agentId);\n total += weight;\n const effectiveWeight = weight * vote.confidence;\n if (vote.decision === 'approve') approval += effectiveWeight;\n else if (vote.decision === 'reject') rejection += effectiveWeight;\n }\n return { approval, rejection, total, agents, breakdown };\n }\n\n private logConsensusResult(result: WeightedConsensusResult): void {\n logger.info('Weighted consensus calculated', {\n decision: result.decision,\n approval: result.weightedApproval.toFixed(3),\n rejection: result.weightedRejection.toFixed(3),\n totalWeight: result.totalWeight.toFixed(3),\n quorumReached: result.quorumReached,\n byzantineDetected: result.byzantineDetected,\n });\n }\n\n private emitWeightChange(\n agentId: string,\n prev: number,\n next: number,\n reason: 'performance_update' | 'flag_penalty' | 'recalibration'\n ): void {\n if (this.emitEvents && this.eventBus !== undefined && prev !== next) {\n emitWeightUpdated(this.eventBus, { agentId, previousWeight: prev, newWeight: next, reason });\n }\n }\n\n private emitAgentFlaggedEvent(\n agentId: string,\n reason: string,\n previousWeight: number,\n canVote: boolean\n ): void {\n if (this.emitEvents && this.eventBus !== undefined) {\n emitAgentFlagged(this.eventBus, { agentId, reason, previousWeight, canVote });\n }\n }\n\n private excludeAgent(record: MutableAgentRecord): void {\n const weightBefore = record.weight;\n record.trustScore = 0;\n record.weight = 0;\n this.emitWeightChange(record.agentId, weightBefore, 0, 'flag_penalty');\n logger.warn('Agent excluded from voting due to Byzantine behavior', {\n agentId: record.agentId,\n flags: record.byzantineFlags,\n });\n }\n\n private detectByzantinePatterns(\n votes: ReadonlyMap<string, Vote>,\n weights: Map<string, number>\n ): boolean {\n const voteArray = Array.from(votes.entries());\n if (voteArray.length < 3) return false;\n const majorityApprove = computeMajorityDirection(voteArray, weights);\n if (this.detectContrarianByzantine(voteArray, majorityApprove)) return true;\n return this.detectCollusionPattern(voteArray);\n }\n\n private detectContrarianByzantine(\n voteArray: Array<[string, Vote]>,\n majorityApprove: boolean\n ): boolean {\n const contrarianAgents: string[] = [];\n for (const [agentId, vote] of voteArray) {\n if (!isLowConfidenceContrarian(vote, majorityApprove)) continue;\n const record = this.records.get(agentId);\n if (record !== undefined && record.byzantineFlags >= 2) {\n contrarianAgents.push(agentId);\n }\n }\n if (contrarianAgents.length > 0) {\n this.emitContrarianPattern(contrarianAgents);\n return true;\n }\n return false;\n }\n\n private emitContrarianPattern(agents: string[]): void {\n if (this.emitEvents && this.eventBus !== undefined) {\n emitPatternDetected(this.eventBus, {\n patternType: 'contrarian',\n agentIds: agents,\n confidence: 0.8,\n details: `${String(agents.length)} agent(s) with Byzantine flags voting contrary to majority with low confidence`,\n });\n }\n }\n\n private detectCollusionPattern(voteArray: Array<[string, Vote]>): boolean {\n const voteSignatures = groupVotesBySignature(voteArray);\n const threshold = voteArray.length * 0.6;\n for (const [signature, agents] of voteSignatures.entries()) {\n if (agents.length >= 3 && agents.length > threshold) {\n this.emitCollusionEvents(agents, signature, voteArray.length);\n return true;\n }\n }\n return false;\n }\n\n private emitCollusionEvents(agents: string[], signature: string, totalVotes: number): void {\n if (this.emitEvents && this.eventBus !== undefined) {\n emitPatternDetected(this.eventBus, {\n patternType: 'collusion',\n agentIds: agents,\n confidence: Math.min(0.95, agents.length / totalVotes),\n details: `${String(agents.length)} agents voting identically: ${signature}`,\n });\n emitCollusionSuspected(this.eventBus, {\n groupAgentIds: agents,\n groupSize: agents.length,\n votingBlock: agents.length / totalVotes,\n threshold: 0.6,\n });\n }\n }\n}\n\n/** Create a weighted voting instance. */\nexport function createWeightedVoting(options?: WeightedVotingOptions): IWeightedVoting {\n return new WeightedVoting(options);\n}\n","/**\n * nexus-agents/consensus - Correlation Helpers\n *\n * Helper functions for correlation tracking and independent subset partitioning.\n * Extracted from correlation-tracker.ts to maintain file size limits.\n *\n * @module consensus/correlation-helpers\n * (Source: Issue #339)\n */\n\nimport type {\n CorrelationMatrix,\n CorrelationCoefficient,\n IndependentSubset,\n VotingObservation,\n HigherOrderVotingConfig,\n AgentPairKey,\n} from './higher-order-types.js';\nimport { createAgentPairKey } from './higher-order-types.js';\n\n// ============================================================================\n// Pairwise History Types\n// ============================================================================\n\n/**\n * Internal mutable representation of pairwise history.\n */\nexport interface MutablePairwiseHistory {\n pairKey: AgentPairKey;\n jointObservations: number;\n agreements: number;\n disagreements: number;\n correlation: CorrelationCoefficient;\n lastUpdated: Date;\n}\n\n// ============================================================================\n// Vote Agreement\n// ============================================================================\n\n/**\n * Check if two observations are comparable (neither is an abstain).\n * Abstain votes should be excluded from correlation tracking.\n *\n * @param obsA - First observation\n * @param obsB - Second observation\n * @returns True if both observations have non-abstain decisions\n */\nexport function isComparable(obsA: VotingObservation, obsB: VotingObservation): boolean {\n return obsA.decision !== 'abstain' && obsB.decision !== 'abstain';\n}\n\n/**\n * Check if two votes agree.\n * Only call this after verifying isComparable() returns true.\n * Abstains are treated as neutral - neither agree nor disagree.\n *\n * @param obsA - First observation\n * @param obsB - Second observation\n * @returns True if votes agree, null if either is an abstain (neutral)\n */\nexport function votesAgree(obsA: VotingObservation, obsB: VotingObservation): boolean | null {\n if (obsA.decision === 'abstain' || obsB.decision === 'abstain') {\n return null; // Neutral — skip this pair (Issue #763)\n }\n return obsA.decision === obsB.decision;\n}\n\n/**\n * Check if a decision aligned with the outcome.\n *\n * @param decision - The voting decision\n * @param outcome - The final outcome\n * @returns True if decision aligned with outcome\n */\nexport function didAlignWithOutcome(decision: string, outcome: 'approved' | 'rejected'): boolean {\n if (decision === 'abstain') return true;\n return (\n (decision === 'approve' && outcome === 'approved') ||\n (decision === 'reject' && outcome === 'rejected')\n );\n}\n\n// ============================================================================\n// Correlation Computation\n// ============================================================================\n\n/**\n * Compute correlation coefficient from pairwise history.\n *\n * Simple correlation: (agreements - disagreements) / total\n * Range: -1 (always disagree) to +1 (always agree)\n *\n * @param history - Pairwise history\n * @returns Correlation coefficient\n */\nexport function computeCorrelationCoefficient(\n history: MutablePairwiseHistory\n): CorrelationCoefficient {\n const n = history.jointObservations;\n if (n === 0) return 0;\n\n // Map agreement/disagreement rates to [-1, 1] correlation\n // 0.5 agreement rate = 0 correlation (random)\n // 1.0 agreement rate = +1 correlation (perfect agreement)\n // 0.0 agreement rate = -1 correlation (perfect disagreement)\n const agreementRate = history.agreements / n;\n const disagreementRate = history.disagreements / n;\n\n return agreementRate - disagreementRate;\n}\n\n// ============================================================================\n// Independent Subset Partitioning\n// ============================================================================\n\n/**\n * Check if an agent is independent from all members of a subset.\n *\n * @param agent - Agent to check\n * @param subset - Existing subset members\n * @param correlationMatrix - Correlation matrix\n * @param independenceThreshold - Maximum correlation for independence\n * @returns True if agent is independent from subset\n */\nexport function isIndependentFromSubset(\n agent: string,\n subset: readonly string[],\n correlationMatrix: CorrelationMatrix,\n independenceThreshold: number\n): boolean {\n for (const member of subset) {\n const pairKey = createAgentPairKey(agent, member);\n const correlation = correlationMatrix.get(pairKey);\n\n // If we don't have data, assume independent\n if (correlation === undefined) continue;\n\n // If correlation exceeds threshold, not independent\n if (Math.abs(correlation) > independenceThreshold) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Compute the average absolute correlation within a subset.\n *\n * @param subset - Agent IDs in the subset\n * @param correlationMatrix - Correlation matrix\n * @returns Average absolute correlation (0 if no pairs)\n */\nexport function computeSubsetIndependenceScore(\n subset: readonly string[],\n correlationMatrix: CorrelationMatrix\n): number {\n if (subset.length < 2) return 0;\n\n let totalCorrelation = 0;\n let pairs = 0;\n\n for (let i = 0; i < subset.length; i++) {\n for (let j = i + 1; j < subset.length; j++) {\n const agentA = subset[i];\n const agentB = subset[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n const correlation = correlationMatrix.get(pairKey);\n if (correlation !== undefined) {\n totalCorrelation += Math.abs(correlation);\n pairs++;\n }\n }\n }\n }\n\n return pairs > 0 ? totalCorrelation / pairs : 0;\n}\n\n/**\n * Compute the minimum observation count for pairs within a subset.\n *\n * @param subset - Agent IDs in the subset\n * @param pairwiseHistory - Map of pairwise histories\n * @returns Minimum observation count (0 if no history)\n */\nexport function computeSubsetObservationCount(\n subset: readonly string[],\n pairwiseHistory: ReadonlyMap<AgentPairKey, MutablePairwiseHistory>\n): number {\n let minObservations = Infinity;\n\n for (let i = 0; i < subset.length; i++) {\n for (let j = i + 1; j < subset.length; j++) {\n const agentA = subset[i];\n const agentB = subset[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n const history = pairwiseHistory.get(pairKey);\n if (history !== undefined) {\n minObservations = Math.min(minObservations, history.jointObservations);\n } else {\n minObservations = 0;\n }\n }\n }\n }\n\n return minObservations === Infinity ? 0 : minObservations;\n}\n\n/**\n * Partition agents into independent groups using greedy clustering.\n *\n * @param agents - List of agent IDs\n * @param correlationMatrix - Correlation matrix\n * @param pairwiseHistory - Map of pairwise histories\n * @param config - Higher-order voting configuration\n * @returns Array of independent subsets\n */\nexport function partitionIntoIndependentGroups(\n agents: readonly string[],\n correlationMatrix: CorrelationMatrix,\n pairwiseHistory: ReadonlyMap<AgentPairKey, MutablePairwiseHistory>,\n config: HigherOrderVotingConfig\n): IndependentSubset[] {\n if (agents.length === 0) return [];\n\n const subsets: IndependentSubset[] = [];\n const assigned = new Set<string>();\n let subsetId = 0;\n\n for (const agent of agents) {\n if (assigned.has(agent)) continue;\n\n const subset: string[] = [agent];\n assigned.add(agent);\n\n // Try to add other unassigned agents if they're independent\n for (const other of agents) {\n if (assigned.has(other)) continue;\n if (isIndependentFromSubset(other, subset, correlationMatrix, config.independenceThreshold)) {\n subset.push(other);\n assigned.add(other);\n }\n }\n\n const independenceScore = computeSubsetIndependenceScore(subset, correlationMatrix);\n const observationCount = computeSubsetObservationCount(subset, pairwiseHistory);\n\n subsets.push({\n id: `subset-${String(subsetId++)}`,\n agentIds: subset,\n independenceScore,\n observationCount,\n });\n }\n\n return subsets;\n}\n","/**\n * nexus-agents/consensus - Correlation Tracker\n *\n * Tracks voting history and computes pairwise correlations between agents.\n * Used by higher-order voting methods to account for agent dependencies.\n *\n * @module consensus/correlation-tracker\n * (Source: Issue #333)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\nimport type { Vote } from './types-core.js';\nimport type {\n ICorrelationTracker,\n CorrelationMatrix,\n CorrelationCoefficient,\n IndependentSubset,\n VotingObservation,\n HigherOrderVotingConfig,\n CorrelationTrackerStats,\n AgentPairKey,\n} from './higher-order-types.js';\nimport { createAgentPairKey, DEFAULT_HIGHER_ORDER_CONFIG } from './higher-order-types.js';\nimport {\n type MutablePairwiseHistory,\n isComparable,\n votesAgree,\n didAlignWithOutcome,\n computeCorrelationCoefficient,\n partitionIntoIndependentGroups,\n} from './correlation-helpers.js';\n\n// Re-export helper types and functions for convenience\nexport type { MutablePairwiseHistory } from './correlation-helpers.js';\nexport {\n isComparable,\n votesAgree,\n didAlignWithOutcome,\n computeCorrelationCoefficient,\n isIndependentFromSubset,\n computeSubsetIndependenceScore,\n computeSubsetObservationCount,\n partitionIntoIndependentGroups,\n} from './correlation-helpers.js';\n\nconst logger = createLogger({ component: 'correlation-tracker' });\n\n/**\n * Correlation tracker implementation.\n * Records voting history and computes pairwise agent correlations.\n *\n * Memory bounded: uses FIFO eviction when maxObservationsPerAgent or maxProposals limits reached.\n */\nexport class CorrelationTracker implements ICorrelationTracker {\n private readonly config: HigherOrderVotingConfig;\n private readonly observations: Map<string, VotingObservation[]> = new Map();\n private readonly pairwiseHistory: Map<AgentPairKey, MutablePairwiseHistory> = new Map();\n private readonly agentProposals: Map<string, Map<string, VotingObservation>> = new Map();\n /** Ordered list of proposal IDs for FIFO eviction */\n private readonly proposalOrder: string[] = [];\n private cachedSubsets: IndependentSubset[] | null = null;\n\n constructor(config?: Partial<HigherOrderVotingConfig>) {\n this.config = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...config };\n logger.info('CorrelationTracker initialized', {\n maxObservationsPerAgent: this.config.maxObservationsPerAgent,\n maxProposals: this.config.maxProposals,\n });\n }\n\n recordVote(agentId: string, vote: Vote, outcome: 'approved' | 'rejected'): void {\n const proposalId = `proposal-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;\n const observation: VotingObservation = {\n proposalId,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n alignedWithOutcome: didAlignWithOutcome(vote.decision, outcome),\n timestamp: new Date(getTimeProvider().now()),\n };\n this.storeObservation(agentId, observation);\n this.invalidateCache();\n }\n\n recordProposalVotes(\n proposalId: string,\n votes: ReadonlyMap<string, Vote>,\n outcome: 'approved' | 'rejected'\n ): void {\n // FIFO eviction when proposal limit reached (Issue #521)\n this.evictOldProposalsIfNeeded();\n\n const proposalObservations: VotingObservation[] = [];\n\n for (const [agentId, vote] of votes) {\n const observation: VotingObservation = {\n proposalId,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n alignedWithOutcome: didAlignWithOutcome(vote.decision, outcome),\n timestamp: new Date(getTimeProvider().now()),\n };\n this.storeObservation(agentId, observation);\n this.storeAgentProposal(agentId, proposalId, observation);\n proposalObservations.push(observation);\n }\n\n // Track proposal order for FIFO eviction\n this.proposalOrder.push(proposalId);\n\n this.updatePairwiseCorrelations(proposalId, proposalObservations);\n this.invalidateCache();\n\n logger.debug('Recorded proposal votes', {\n proposalId,\n agentCount: votes.size,\n outcome,\n totalProposals: this.proposalOrder.length,\n });\n }\n\n computeCorrelationMatrix(): CorrelationMatrix {\n const matrix: CorrelationMatrix = new Map();\n\n for (const [pairKey, history] of this.pairwiseHistory) {\n if (history.jointObservations >= this.config.minObservationsForCorrelation) {\n matrix.set(pairKey, history.correlation);\n }\n }\n\n return matrix;\n }\n\n getCorrelation(agentA: string, agentB: string): CorrelationCoefficient | undefined {\n const pairKey = createAgentPairKey(agentA, agentB);\n const history = this.pairwiseHistory.get(pairKey);\n\n if (history === undefined) return undefined;\n if (history.jointObservations < this.config.minObservationsForCorrelation) return undefined;\n\n return history.correlation;\n }\n\n identifyIndependentSubsets(): readonly IndependentSubset[] {\n if (this.cachedSubsets !== null) return this.cachedSubsets;\n\n const agents = this.getTrackedAgents();\n if (agents.length === 0) {\n this.cachedSubsets = [];\n return this.cachedSubsets;\n }\n\n const correlationMatrix = this.computeCorrelationMatrix();\n const subsets = partitionIntoIndependentGroups(\n agents,\n correlationMatrix,\n this.pairwiseHistory,\n this.config\n );\n\n this.cachedSubsets = subsets;\n logger.debug('Identified independent subsets', {\n agentCount: agents.length,\n subsetCount: subsets.length,\n });\n\n return subsets;\n }\n\n hasSufficientData(agentIds: readonly string[]): boolean {\n if (agentIds.length < 2) return true;\n\n let pairsWithData = 0;\n const totalPairs = (agentIds.length * (agentIds.length - 1)) / 2;\n\n for (let i = 0; i < agentIds.length; i++) {\n for (let j = i + 1; j < agentIds.length; j++) {\n const agentA = agentIds[i];\n const agentB = agentIds[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n const history = this.pairwiseHistory.get(pairKey);\n if (\n history !== undefined &&\n history.jointObservations >= this.config.minObservationsForCorrelation\n ) {\n pairsWithData++;\n }\n }\n }\n }\n\n // Require at least 50% of pairs to have sufficient data\n return pairsWithData >= totalPairs * 0.5;\n }\n\n getStats(): CorrelationTrackerStats {\n const agents = this.getTrackedAgents();\n // Used by callers to understand full correlation state\n void this.computeCorrelationMatrix();\n const subsets = this.identifyIndependentSubsets();\n\n let totalCorrelation = 0;\n let pairsWithSufficientData = 0;\n\n for (const [, history] of this.pairwiseHistory) {\n if (history.jointObservations >= this.config.minObservationsForCorrelation) {\n totalCorrelation += history.correlation;\n pairsWithSufficientData++;\n }\n }\n\n let totalObservations = 0;\n for (const obs of this.observations.values()) {\n totalObservations += obs.length;\n }\n\n return {\n totalAgents: agents.length,\n trackedPairs: this.pairwiseHistory.size,\n totalObservations,\n averageCorrelation:\n pairsWithSufficientData > 0 ? totalCorrelation / pairsWithSufficientData : 0,\n independentSubsetCount: subsets.length,\n pairsWithSufficientData,\n };\n }\n\n clear(): void {\n this.observations.clear();\n this.pairwiseHistory.clear();\n this.agentProposals.clear();\n this.proposalOrder.length = 0;\n this.cachedSubsets = null;\n logger.info('CorrelationTracker cleared');\n }\n\n // ============================================================================\n // Private helpers\n // ============================================================================\n\n /**\n * Evict oldest proposals when maxProposals limit is reached.\n * Also cleans up agentProposals entries for evicted proposals.\n */\n private evictOldProposalsIfNeeded(): void {\n while (this.proposalOrder.length >= this.config.maxProposals) {\n const evictedProposalId = this.proposalOrder.shift();\n if (evictedProposalId === undefined) break;\n\n // Clean up agentProposals for the evicted proposal\n for (const [agentId, proposalMap] of this.agentProposals) {\n if (proposalMap.has(evictedProposalId)) {\n proposalMap.delete(evictedProposalId);\n // Clean up empty agent entries\n if (proposalMap.size === 0) {\n this.agentProposals.delete(agentId);\n }\n }\n }\n\n logger.debug('Evicted oldest proposal', {\n evictedProposalId,\n reason: 'maxProposals',\n remainingProposals: this.proposalOrder.length,\n });\n }\n }\n\n /**\n * Evict the oldest pairwise history entry (by lastUpdated) when\n * maxTrackedPairs limit is exceeded.\n */\n private evictOldestPair(): void {\n if (this.pairwiseHistory.size <= this.config.maxTrackedPairs) return;\n\n let oldestKey: AgentPairKey | undefined;\n let oldestTime = Infinity;\n for (const [key, history] of this.pairwiseHistory) {\n const time = history.lastUpdated.getTime();\n if (time < oldestTime) {\n oldestTime = time;\n oldestKey = key;\n }\n }\n if (oldestKey !== undefined) {\n this.pairwiseHistory.delete(oldestKey);\n logger.debug('Evicted oldest pairwise history entry', {\n evictedKey: oldestKey,\n reason: 'maxTrackedPairs',\n remainingPairs: this.pairwiseHistory.size,\n });\n }\n }\n\n private storeObservation(agentId: string, observation: VotingObservation): void {\n let agentObs = this.observations.get(agentId);\n if (agentObs === undefined) {\n agentObs = [];\n this.observations.set(agentId, agentObs);\n }\n\n // FIFO eviction when per-agent limit reached (Issue #521)\n while (agentObs.length >= this.config.maxObservationsPerAgent) {\n const evicted = agentObs.shift();\n if (evicted !== undefined) {\n logger.debug('Evicted oldest observation for agent', {\n agentId,\n evictedProposalId: evicted.proposalId,\n reason: 'maxObservationsPerAgent',\n });\n }\n }\n\n agentObs.push(observation);\n }\n\n private storeAgentProposal(\n agentId: string,\n proposalId: string,\n observation: VotingObservation\n ): void {\n let agentProposalMap = this.agentProposals.get(agentId);\n if (agentProposalMap === undefined) {\n agentProposalMap = new Map();\n this.agentProposals.set(agentId, agentProposalMap);\n }\n agentProposalMap.set(proposalId, observation);\n }\n\n private updatePairwiseCorrelations(proposalId: string, observations: VotingObservation[]): void {\n for (let i = 0; i < observations.length; i++) {\n for (let j = i + 1; j < observations.length; j++) {\n const obsA = observations[i];\n const obsB = observations[j];\n if (obsA === undefined || obsB === undefined) continue;\n\n const pairKey = createAgentPairKey(obsA.agentId, obsB.agentId);\n let history = this.pairwiseHistory.get(pairKey);\n\n if (history === undefined) {\n history = {\n pairKey,\n jointObservations: 0,\n agreements: 0,\n disagreements: 0,\n correlation: 0,\n lastUpdated: new Date(getTimeProvider().now()),\n };\n this.pairwiseHistory.set(pairKey, history);\n this.evictOldestPair();\n }\n\n // Skip abstain observations — they are neutral (Issue #763)\n if (!isComparable(obsA, obsB)) continue;\n\n history.jointObservations++;\n const agreed = votesAgree(obsA, obsB);\n if (agreed === true) {\n history.agreements++;\n } else {\n history.disagreements++;\n }\n\n history.correlation = computeCorrelationCoefficient(history);\n history.lastUpdated = new Date(getTimeProvider().now());\n }\n }\n }\n\n private getTrackedAgents(): string[] {\n return Array.from(this.observations.keys());\n }\n\n private invalidateCache(): void {\n this.cachedSubsets = null;\n }\n}\n\n/**\n * Creates a new correlation tracker instance.\n */\nexport function createCorrelationTracker(\n config?: Partial<HigherOrderVotingConfig>\n): ICorrelationTracker {\n return new CorrelationTracker(config);\n}\n","/**\n * nexus-agents/consensus - Correlation Persistence\n *\n * Disk persistence for CorrelationTracker voting history. Enables Higher-Order\n * Voting (HOV) to accumulate correlation data across process restarts,\n * activating Bayesian correlation awareness.\n *\n * Storage: append-only JSONL at `~/.nexus-agents/voting/correlations.jsonl`\n * (mode 0o600). Each line is one `PersistedProposal`. Append-only avoids the\n * cross-process read-merge-rename race the previous `correlations.json`\n * design had (#2973): two processes voting concurrently each loaded N\n * entries, each merged their own proposal, each renamed over the same file,\n * losing the loser's proposal. Append guarantees atomic-per-line writes on\n * POSIX so concurrent writers are race-free.\n *\n * Reads dedupe by `proposalId` (last write wins) and apply FIFO eviction\n * past `maxProposals`. A legacy `correlations.json` is read alongside the\n * JSONL on first load (its entries are surfaced like any other history) and\n * is removed by `compactCorrelationData()` after consolidation. New writes\n * always go to the JSONL.\n *\n * @module consensus/correlation-persistence\n * (Source: Issue #514; #2973 for the JSONL switch)\n */\n\nimport * as fs from 'node:fs';\nimport { nexusDataPath } from '../config/nexus-data-dir.js';\nimport { z } from 'zod';\nimport type { Result } from '../core/result.js';\nimport { ok, err } from '../core/result.js';\nimport type { ILogger } from '../core/logger.js';\nimport { createLogger } from '../core/logger.js';\nimport type { ICorrelationTracker, HigherOrderVotingConfig } from './higher-order-types.js';\nimport { DEFAULT_HIGHER_ORDER_CONFIG } from './higher-order-types.js';\nimport type { Vote } from './types-core.js';\nimport { createCorrelationTracker } from './correlation-tracker.js';\n\nconst logger: ILogger = createLogger({ component: 'correlation-persistence' });\n\n/** Subdirectory name under the resolved nexus data dir for voting data. */\nconst VOTING_SUBDIR = 'voting';\n\n/** Legacy single-JSON file (pre-#2973). Still read on load; never written. */\nconst CORRELATIONS_FILE = 'correlations.json';\n\n/** Active append-only JSONL store (#2973). */\nconst CORRELATIONS_JSONL_FILE = 'correlations.jsonl';\n\n/** File permissions: user read/write only */\nconst FILE_MODE = 0o600;\n\n/** Directory permissions: user read/write/execute only */\nconst DIR_MODE = 0o700;\n\n/** Schema version for forward compatibility. Bumped to 2 with the JSONL switch. */\nconst SCHEMA_VERSION = 2;\n\n// ============================================================================\n// Persisted Data Types\n// ============================================================================\n\n/**\n * A single persisted vote within a proposal.\n */\nconst PersistedVoteSchema = z.object({\n agentId: z.string(),\n decision: z.enum(['approve', 'reject', 'abstain']),\n confidence: z.number().min(0).max(1),\n});\n\n/** Type for a persisted vote entry */\ntype PersistedVote = z.infer<typeof PersistedVoteSchema>;\n\n/**\n * A persisted proposal with its votes and outcome.\n * Stored as a replayable record so internal tracker state\n * is reconstructed through the public API.\n */\nconst PersistedProposalSchema = z.object({\n proposalId: z.string(),\n votes: z.array(PersistedVoteSchema),\n outcome: z.enum(['approved', 'rejected']),\n timestamp: z.iso.datetime(),\n});\n\n/** Type for a persisted proposal entry */\ntype PersistedProposal = z.infer<typeof PersistedProposalSchema>;\n\n/**\n * Top-level persisted correlation data structure (legacy `correlations.json`).\n * Kept exported for back-compat — the JSONL format stores `PersistedProposal`\n * directly per line and has no wrapper.\n */\nexport const PersistedCorrelationDataSchema = z.object({\n version: z.number().int().positive(),\n proposals: z.array(PersistedProposalSchema),\n savedAt: z.iso.datetime(),\n});\n\n/** Validated persisted correlation data */\nexport type PersistedCorrelationData = z.infer<typeof PersistedCorrelationDataSchema>;\n\n// ============================================================================\n// Path Helpers\n// ============================================================================\n\n/**\n * Returns the absolute path to the **legacy** correlation data file. Kept\n * for back-compat — new writes go through `getCorrelationJsonlPath()`.\n */\nexport function getCorrelationDataPath(): string {\n return nexusDataPath(VOTING_SUBDIR, CORRELATIONS_FILE);\n}\n\n/** Returns the absolute path to the active JSONL store (#2973). */\nexport function getCorrelationJsonlPath(): string {\n return nexusDataPath(VOTING_SUBDIR, CORRELATIONS_JSONL_FILE);\n}\n\n/**\n * Ensures the voting data directory exists with appropriate permissions.\n */\nfunction ensureVotingDirectory(): Result<void, Error> {\n const dirPath = nexusDataPath(VOTING_SUBDIR);\n try {\n fs.mkdirSync(dirPath, { recursive: true, mode: DIR_MODE });\n return ok(undefined);\n } catch (cause: unknown) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n return err(new Error(`Failed to create voting directory at ${dirPath}: ${error.message}`));\n }\n}\n\n// ============================================================================\n// Save (append-only, race-free across processes)\n// ============================================================================\n\n/**\n * Appends new proposals to the JSONL store. One line per proposal.\n *\n * POSIX `O_APPEND` (used implicitly by `appendFileSync` with `{flag: 'a'}`)\n * guarantees atomic writes for buffer sizes under `PIPE_BUF` (4 KB on Linux,\n * 512 B on macOS). Each line we write is a single `PersistedProposal` — well\n * under those limits in practice for the typical vote-panel size (3–7 voters).\n * Two processes calling this concurrently get all proposals persisted; no\n * read-merge-rename race possible because we never read or rename.\n *\n * @param proposals - Array of proposals with their votes and outcomes to persist\n * @param _config - Higher-order voting config (only `maxProposals` is consulted\n * on read; this writer is fully append-only)\n * @returns Result indicating success or failure\n */\nexport function saveCorrelationData(\n proposals: PersistedProposal[],\n // config kept in the signature for ABI compatibility with the legacy\n // implementation; the JSONL writer is append-only so we don't need it here.\n // FIFO truncation happens on read.\n _config: HigherOrderVotingConfig = DEFAULT_HIGHER_ORDER_CONFIG\n): Result<void, Error> {\n const dirResult = ensureVotingDirectory();\n if (!dirResult.ok) return dirResult;\n\n if (proposals.length === 0) return ok(undefined);\n\n const filePath = getCorrelationJsonlPath();\n\n try {\n const lines = proposals.map((p) => JSON.stringify(p)).join('\\n') + '\\n';\n fs.appendFileSync(filePath, lines, { encoding: 'utf-8', mode: FILE_MODE });\n\n logger.info('Correlation proposals appended', {\n path: filePath,\n proposalCount: proposals.length,\n });\n\n return ok(undefined);\n } catch (cause: unknown) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n return err(new Error(`Failed to append correlation data: ${error.message}`));\n }\n}\n\n// ============================================================================\n// Load (consolidates JSONL + legacy JSON, dedupes by proposalId, FIFO-truncates)\n// ============================================================================\n\n/** Read the legacy `correlations.json` if present; return [] otherwise. */\nfunction loadLegacyJsonProposals(): PersistedProposal[] {\n const filePath = getCorrelationDataPath();\n if (!fs.existsSync(filePath)) return [];\n\n let rawContent: string;\n try {\n rawContent = fs.readFileSync(filePath, { encoding: 'utf-8' });\n } catch (cause: unknown) {\n logger.warn('Failed to read legacy correlations.json', {\n path: filePath,\n error: cause instanceof Error ? cause.message : String(cause),\n });\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawContent);\n } catch (cause: unknown) {\n logger.warn('Corrupt legacy correlations.json — skipping', {\n path: filePath,\n error: cause instanceof Error ? cause.message : String(cause),\n });\n return [];\n }\n\n const result = PersistedCorrelationDataSchema.safeParse(parsed);\n if (!result.success) {\n logger.warn('Invalid legacy correlations.json schema — skipping', {\n path: filePath,\n error: result.error.message,\n });\n return [];\n }\n return result.data.proposals;\n}\n\ntype LineResult = { kind: 'ok'; proposal: PersistedProposal } | { kind: 'skip'; reason: string };\n\n/** Parse one JSONL line into a typed result so the loader can stay below max-complexity. */\nfunction parseJsonlLine(line: string): LineResult {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch (cause: unknown) {\n return {\n kind: 'skip',\n reason: `JSON.parse: ${cause instanceof Error ? cause.message : String(cause)}`,\n };\n }\n const result = PersistedProposalSchema.safeParse(parsed);\n if (!result.success) return { kind: 'skip', reason: `schema: ${result.error.message}` };\n return { kind: 'ok', proposal: result.data };\n}\n\n/** Read JSONL store, dropping malformed lines with a warn log. */\nfunction loadJsonlProposals(): PersistedProposal[] {\n const filePath = getCorrelationJsonlPath();\n if (!fs.existsSync(filePath)) return [];\n\n let content: string;\n try {\n content = fs.readFileSync(filePath, { encoding: 'utf-8' });\n } catch (cause: unknown) {\n logger.warn('Failed to read correlations.jsonl', {\n path: filePath,\n error: cause instanceof Error ? cause.message : String(cause),\n });\n return [];\n }\n\n const lines = content.split('\\n').filter((line) => line.trim() !== '');\n const proposals: PersistedProposal[] = [];\n let skippedCount = 0;\n let firstSkipReason: string | undefined;\n\n for (const line of lines) {\n const result = parseJsonlLine(line);\n if (result.kind === 'ok') {\n proposals.push(result.proposal);\n } else {\n skippedCount++;\n firstSkipReason ??= result.reason;\n }\n }\n\n if (skippedCount > 0) {\n logger.warn('Skipped malformed lines in correlations.jsonl', {\n path: filePath,\n skippedCount,\n totalLines: lines.length,\n firstSkipReason,\n });\n }\n\n return proposals;\n}\n\n/**\n * Combines proposals from both stores, dedupes by proposalId (later wins),\n * sorts by timestamp ascending, and FIFO-truncates to `maxProposals`.\n */\nfunction consolidate(\n legacyProposals: PersistedProposal[],\n jsonlProposals: PersistedProposal[],\n maxProposals: number\n): PersistedProposal[] {\n const proposalMap = new Map<string, PersistedProposal>();\n // Legacy first, then JSONL — JSONL entries override legacy if same id.\n for (const p of legacyProposals) proposalMap.set(p.proposalId, p);\n for (const p of jsonlProposals) proposalMap.set(p.proposalId, p);\n\n const all = Array.from(proposalMap.values()).sort((a, b) =>\n a.timestamp.localeCompare(b.timestamp)\n );\n return all.length > maxProposals ? all.slice(all.length - maxProposals) : all;\n}\n\n/**\n * Loads and validates correlation data from disk. Combines the JSONL store\n * with the legacy `correlations.json` (if present). Always returns an Ok\n * result when the directory exists; an empty proposals array means \"no\n * persisted history\" (formerly the \"not found\" error case).\n */\nexport function loadCorrelationData(\n config: HigherOrderVotingConfig = DEFAULT_HIGHER_ORDER_CONFIG\n): Result<PersistedCorrelationData, Error> {\n const jsonlPath = getCorrelationJsonlPath();\n const legacyPath = getCorrelationDataPath();\n const jsonlExists = fs.existsSync(jsonlPath);\n const legacyExists = fs.existsSync(legacyPath);\n\n if (!jsonlExists && !legacyExists) {\n return err(new Error(`Correlation data file not found: ${jsonlPath}`));\n }\n\n const legacy = loadLegacyJsonProposals();\n const jsonl = loadJsonlProposals();\n const proposals = consolidate(legacy, jsonl, config.maxProposals);\n\n logger.info('Correlation data loaded', {\n legacyCount: legacy.length,\n jsonlCount: jsonl.length,\n afterDedup: proposals.length,\n });\n\n return ok({\n version: SCHEMA_VERSION,\n proposals,\n savedAt: new Date().toISOString(),\n });\n}\n\n// ============================================================================\n// Compaction (consolidate JSONL + delete legacy json)\n// ============================================================================\n\n/**\n * Rewrites the JSONL store as a deduplicated, sorted snapshot and removes\n * the legacy `correlations.json` (if present). Safe to call periodically\n * (e.g., on session shutdown) to bound the JSONL's size.\n *\n * Within-process: this is the only operation that's NOT race-free across\n * processes. Two processes both running compaction simultaneously could\n * lose appends made between the read and the rename. Callers should\n * serialize compaction — invoke from one process per data dir, or guard\n * with a lockfile.\n */\nexport function compactCorrelationData(\n config: HigherOrderVotingConfig = DEFAULT_HIGHER_ORDER_CONFIG\n): Result<{ before: number; after: number }, Error> {\n const dirResult = ensureVotingDirectory();\n if (!dirResult.ok) return dirResult;\n\n const legacy = loadLegacyJsonProposals();\n const jsonl = loadJsonlProposals();\n const proposals = consolidate(legacy, jsonl, config.maxProposals);\n const before = legacy.length + jsonl.length;\n\n const jsonlPath = getCorrelationJsonlPath();\n const tempPath = `${jsonlPath}.tmp.${String(process.pid)}`;\n const body =\n proposals.map((p) => JSON.stringify(p)).join('\\n') + (proposals.length > 0 ? '\\n' : '');\n\n try {\n fs.writeFileSync(tempPath, body, { encoding: 'utf-8', mode: FILE_MODE });\n fs.renameSync(tempPath, jsonlPath);\n if (fs.existsSync(getCorrelationDataPath())) {\n fs.unlinkSync(getCorrelationDataPath());\n }\n return ok({ before, after: proposals.length });\n } catch (cause: unknown) {\n try {\n if (fs.existsSync(tempPath)) fs.unlinkSync(tempPath);\n } catch (cleanupErr: unknown) {\n logger.debug('Failed to clean up temp file during compaction', {\n path: tempPath,\n error: cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr),\n });\n }\n const error = cause instanceof Error ? cause : new Error(String(cause));\n return err(new Error(`Failed to compact correlation data: ${error.message}`));\n }\n}\n\n// ============================================================================\n// Persistent Tracker Factory\n// ============================================================================\n\n/**\n * Replays persisted proposals into a tracker via `recordProposalVotes()`,\n * reconstructing all internal state through the public API.\n */\nfunction replayProposals(\n tracker: ICorrelationTracker,\n proposals: readonly PersistedProposal[]\n): number {\n let replayed = 0;\n\n for (const proposal of proposals) {\n const votes = new Map<string, Vote>();\n\n for (const vote of proposal.votes) {\n votes.set(vote.agentId, {\n decision: vote.decision,\n reasoning: 'replayed from persistence',\n confidence: vote.confidence,\n });\n }\n\n tracker.recordProposalVotes(proposal.proposalId, votes, proposal.outcome);\n replayed++;\n }\n\n return replayed;\n}\n\n/**\n * Creates a correlation tracker pre-loaded with persisted history.\n *\n * On first run (no persisted data), returns a fresh tracker.\n * On subsequent runs, replays all stored proposals through the\n * tracker's public API to reconstruct correlation state.\n *\n * This enables Higher-Order Voting to accumulate enough history\n * across process restarts to activate Bayesian correlation awareness.\n *\n * @param config - Optional partial higher-order voting config\n * @returns A correlation tracker with any persisted history replayed\n */\nexport function createPersistentCorrelationTracker(\n config?: Partial<HigherOrderVotingConfig>\n): ICorrelationTracker {\n const tracker = createCorrelationTracker(config);\n\n const mergedConfig = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...config };\n const loadResult = loadCorrelationData(mergedConfig);\n if (!loadResult.ok) {\n logger.info('Starting with fresh correlation tracker', {\n reason: loadResult.error.message,\n });\n return tracker;\n }\n\n const replayedCount = replayProposals(tracker, loadResult.value.proposals);\n\n logger.info('Correlation tracker restored from persistence', {\n replayedProposals: replayedCount,\n stats: tracker.getStats(),\n });\n\n return tracker;\n}\n\n// ============================================================================\n// Proposal Recording Helper\n// ============================================================================\n\n/**\n * Creates a persistable proposal record from vote data.\n *\n * Use this to build proposals that can be passed to `saveCorrelationData()`.\n *\n * @param proposalId - Unique proposal identifier\n * @param votes - Map of agent IDs to their votes\n * @param outcome - Final proposal outcome\n * @returns A persistable proposal record\n */\nexport function createPersistedProposal(\n proposalId: string,\n votes: ReadonlyMap<string, Vote>,\n outcome: 'approved' | 'rejected'\n): PersistedProposal {\n const persistedVotes: PersistedVote[] = [];\n\n for (const [agentId, vote] of votes) {\n persistedVotes.push({\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n });\n }\n\n return {\n proposalId,\n votes: persistedVotes,\n outcome,\n timestamp: new Date().toISOString(),\n };\n}\n","/**\n * Types, schemas, and response helpers for the consensus_vote MCP tool.\n * Extracted from consensus-vote.ts for file size compliance (Issue #708).\n *\n * @module mcp/tools/consensus-vote-types\n */\n\nimport { z } from 'zod';\nimport type { AgentVoteResult, VotingResult } from '../../cli/vote-types.js';\nimport { VOTER_ROLES } from '../../cli/vote-types.js';\nimport type { HigherOrderVotingResult } from '../../consensus/higher-order-types.js';\n\n/** Maximum proposal length (memory bounds per Issue #435). */\nexport const MAX_PROPOSAL_LENGTH = 4000;\n\n// ============================================================================\n// Strategy Types\n// ============================================================================\n\n/**\n * Available consensus voting strategies.\n *\n * - `simple_majority`: Standard majority voting (>50%)\n * - `supermajority`: Requires >=67% approval\n * - `unanimous`: Requires 100% approval\n * - `proof_of_learning`: Weighted by agent performance (Issue #103)\n * - `higher_order`: Bayesian-optimal with correlation awareness (Issue #514)\n * - `opinion_wise`: Alias for higher_order (Issue #333)\n */\nexport type VotingStrategy =\n | 'simple_majority'\n | 'supermajority'\n | 'unanimous'\n | 'proof_of_learning'\n | 'higher_order'\n | 'opinion_wise';\n\nexport const VotingStrategySchema = z.enum([\n 'simple_majority',\n 'supermajority',\n 'unanimous',\n 'proof_of_learning',\n 'higher_order',\n 'opinion_wise',\n]);\n\n/**\n * Whether a strategy uses higher-order (Bayesian, correlation-aware) aggregation.\n * `opinion_wise` is a documented alias of `higher_order` (#333), so both must\n * take the higher-order path — gating on the literal `'higher_order'` silently\n * dropped opinion_wise to the plain engine with no higherOrderMetadata (#3271).\n */\nexport function isHigherOrderStrategy(strategy: VotingStrategy): boolean {\n return strategy === 'higher_order' || strategy === 'opinion_wise';\n}\n\n/**\n * Posterior-approval floor below which a `higher_order` quickMode *approval* is\n * escalated to the full voter panel (#3174). For Bayesian aggregation the\n * posterior is a first-class confidence signal: an approval whose posterior sits\n * near 0.5 means the 3-voter quick panel was barely decisive, which is exactly\n * the case where the extra voters are worth their cost. Mirrors the bare-constant\n * style of `CONTRARIAN_ESCALATION_THRESHOLD`. Set above any real posterior to\n * always escalate, or — since the gate also requires `posterior < floor` — a\n * floor of `0` disables posterior-based escalation entirely.\n */\nexport const HIGHER_ORDER_ESCALATION_POSTERIOR_FLOOR = 0.65;\n\n/**\n * Whether a quickMode approval should escalate to the full panel purely on a\n * borderline Bayesian posterior (#3174). Independent of the contrarian-agent\n * check — this catches low-confidence higher_order approvals that a clean\n * outcome string hides. Only fires for higher_order/opinion_wise (the strategies\n * with a meaningful posterior), on approvals, in quickMode, when the posterior\n * is known and below the floor.\n */\nexport function shouldEscalateLowPosterior(\n strategy: VotingStrategy,\n outcome: 'approved' | 'rejected',\n quickMode: boolean,\n posteriorApproval: number | undefined\n): boolean {\n return (\n quickMode &&\n outcome === 'approved' &&\n isHigherOrderStrategy(strategy) &&\n posteriorApproval !== undefined &&\n posteriorApproval < HIGHER_ORDER_ESCALATION_POSTERIOR_FLOOR\n );\n}\n\n// ============================================================================\n// Input / Output Schemas\n// ============================================================================\n\n/**\n * How error-source votes (timed-out or crashed voters) are counted toward\n * the threshold (#2630).\n *\n * - `reduce_denominator` (default for non-strict strategies): errors are\n * filtered out before the engine sees votes — denominator = non-error\n * votes. Best for operational decisions where you trust the responding\n * voters and infrastructure flake should not block the vote.\n * - `count_as_abstain`: error votes reach the engine as abstain. Behaves\n * conservatively — a timed-out voter effectively withholds approval\n * relative to the threshold. Use when you can't tell what the error\n * voter would have decided and want the math to reflect uncertainty.\n * - `fail_closed` (default for unanimous / higher_order): any error voids\n * the vote. Threshold math is not run. Use for security-critical or\n * breaking-change decisions where every voter must be heard.\n *\n * Regardless of policy, a hard floor applies: when errors exceed 50% of\n * total voters, the vote always fails. Catches \"all CLIs are down\" — a\n * 2-voter consensus is not a real consensus.\n */\nexport const ErrorPolicySchema = z.enum(['reduce_denominator', 'count_as_abstain', 'fail_closed']);\n\nexport type ErrorPolicy = z.infer<typeof ErrorPolicySchema>;\n\n/**\n * Threshold values accepted by the `--threshold` CLI flag and the\n * \\`threshold\\` MCP input field (#2638 — single source of truth).\n *\n * Maps to consensus algorithms via:\n * `majority → simple_majority`, `supermajority → supermajority`, `unanimous → unanimous`.\n *\n * Used as the canonical Zod schema for CLI parsing\n * (`cli.ts:parseThreshold`), validation (`cli-commands-validators.ts:isValidThreshold`),\n * and the `ConsensusVoteInputSchema.threshold` field.\n */\nexport const VoteThresholdSchema = z.enum(['majority', 'supermajority', 'unanimous']);\n\nexport type VoteThreshold = z.infer<typeof VoteThresholdSchema>;\n\n/**\n * Fraction of total voters that, if errored, forces the vote to fail\n * regardless of `errorPolicy`. (#2630 — safety floor.)\n */\nexport const ERROR_FLOOR_FRACTION = 0.5;\n\n/**\n * Default error policy per voting strategy.\n *\n * Only `unanimous` defaults to `fail_closed`: a missing/errored voter genuinely\n * breaks the unanimity guarantee, so the vote must void. Every other strategy —\n * including `higher_order` and its `opinion_wise` alias — defaults to\n * `reduce_denominator`: Bayesian/weighted aggregation over the *non-error*\n * voters is well-defined, so a single infra timeout (e.g. one slow voter's\n * adapter transport, #3304) should NOT fail-close an otherwise-unanimous result\n * (#3138). The >50% `ERROR_FLOOR_FRACTION` hard floor still voids any vote where\n * most voters errored. Callers can override via the `errorPolicy` input.\n */\nexport function getDefaultErrorPolicy(strategy: VotingStrategy): ErrorPolicy {\n if (strategy === 'unanimous') {\n return 'fail_closed';\n }\n return 'reduce_denominator';\n}\n\nexport const ConsensusVoteInputSchema = z.object({\n proposal: z.string().min(1).max(MAX_PROPOSAL_LENGTH).describe('Proposal text to vote on'),\n threshold: VoteThresholdSchema.optional().describe(\n 'Voting threshold (legacy): majority, supermajority, unanimous. Use strategy instead.'\n ),\n strategy: VotingStrategySchema.optional().describe(\n 'Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order (Bayesian-optimal)'\n ),\n errorPolicy: ErrorPolicySchema.optional().describe(\n 'How to treat voters that errored or timed out (#2630). Default: fail_closed for unanimous only; reduce_denominator for all other strategies incl. higher_order/opinion_wise (#3138 — a single infra timeout should not void an otherwise-unanimous vote). Regardless of policy, errors > 50% always fails.'\n ),\n quickMode: z\n .boolean()\n .optional()\n .default(false)\n .describe('Use 3 agents instead of the full 7-role panel for faster execution'),\n simulateVotes: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'TESTS ONLY — when true, voters return random decisions. Output must not be used for real decisions. (#2319)'\n ),\n /**\n * Async-mode dispatch (#3045, Stage 4 of epic #2631). Default `sync` —\n * backward-compat invariant. `async` returns `{ status: 'pending', jobId }`\n * immediately; caller polls `get_job_result(jobId)`. Per-tool cap via\n * `NEXUS_JOB_MAX_CONCURRENT_CONSENSUS_VOTE` (default 2 — voting is\n * 7-fan-out so concurrent jobs multiply adapter load fast).\n *\n * Cancellation semantics (#3041 vote deferred this to Stage 4): when\n * a polling client calls `cancel_job` mid-vote, the dispatcher aborts\n * in-flight voters via the AbortSignal plumbing from #3038. The\n * resulting job result is `{ status: 'cancelled', partialVotes: [...] }`\n * with whatever voters completed before the abort signal — preserves\n * audit visibility into who voted before the cancel landed.\n *\n * Kept optional (no `.default()`) so the inferred type doesn't force\n * `mode: 'sync'` on every existing call site / test fixture.\n */\n mode: z\n .enum(['sync', 'async'])\n .optional()\n .describe(\n 'Dispatch mode (default: sync). Use \"async\" for higher-order strategies with 7 voters.'\n ),\n /**\n * Idempotency key for async-mode replay-safety (#3042 Stage 1c / epic\n * #2631). When set: identical (key, inputs) returns the existing job;\n * same key with different inputs fails closed with\n * `idempotency_key_collision`. Sync mode ignores this.\n */\n idempotencyKey: z\n .string()\n .min(1)\n .max(256)\n .optional()\n .describe(\n 'Replay-safe key for async-mode dispatch (#3042 Stage 1c). Same (key, inputs) returns existing jobId.'\n ),\n});\n\nexport type ConsensusVoteInput = z.infer<typeof ConsensusVoteInputSchema>;\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface AgentVoteSummary {\n role: string;\n decision: 'approve' | 'reject' | 'abstain';\n confidence: number;\n reasoning: string;\n simulated: boolean;\n /** True when this vote was generated from an error (Issue #815). */\n error: boolean;\n /** Model used for this agent's vote (Issue #817). */\n modelUsed?: string;\n /** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */\n rejectionCategories?: readonly string[];\n}\n\nexport type VoteDecisionStatus = 'approved' | 'rejected' | 'pending' | 'timeout' | 'no_quorum';\n\n/** Higher-Order Voting metadata (Issue #514). */\nexport interface HigherOrderMetadata {\n posteriorApproval: number;\n posteriorRejection: number;\n effectiveVoteCount: number;\n method: 'ow' | 'isp' | 'simple';\n usedCorrelationData: boolean;\n improvementOverBaseline: number;\n downweightedAgents: readonly string[];\n reasoning: string;\n}\n\nexport interface ConsensusVoteResponse {\n proposal: string;\n threshold?: VoteThreshold;\n strategy: VotingStrategy;\n decision: VoteDecisionStatus;\n approvalPercentage: number;\n voteCounts: { approve: number; reject: number; abstain: number; error: number };\n votes: AgentVoteSummary[];\n durationMs: number;\n simulateVotes: boolean;\n higherOrderMetadata?: HigherOrderMetadata;\n /**\n * Set when an error policy short-circuited the vote (#2630/#3124). Explains a\n * `rejected` decision that may coexist with a high `approvalPercentage` — e.g.\n * `fail_closed: 1 voter(s) errored`. Absent on normally-tallied votes.\n */\n policyReason?: string;\n /**\n * Set when the panel was DEGRADED (#3587): some voters errored, so the\n * decision rests on fewer than the requested number of voters. Surfaces a\n * silently-shrunk panel so the result isn't read as a full-strength consensus.\n * Absent when every requested voter returned a real vote.\n */\n panelWarning?: string;\n}\n\n/** Extended voting result with optional Higher-Order metadata. */\nexport interface ExtendedVotingResult extends VotingResult {\n strategy: VotingStrategy;\n higherOrderResult?: HigherOrderVotingResult;\n /** Reason an error policy short-circuited the vote (#3124); surfaced on the response. */\n policyReason?: string;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/** Converts AgentVoteResult to AgentVoteSummary for response. */\nexport function toAgentVoteSummary(result: AgentVoteResult): AgentVoteSummary {\n const roleName = VOTER_ROLES[result.role].split(' - ')[0] ?? result.role;\n return {\n role: roleName,\n decision: result.vote.decision,\n confidence: result.vote.confidence,\n reasoning: result.vote.reasoning,\n simulated: result.source === 'simulation',\n error: result.source === 'error',\n ...(result.vote.rejectionCategories !== undefined\n ? { rejectionCategories: result.vote.rejectionCategories }\n : {}),\n };\n}\n\n/** Maps ProposalStatus to VoteDecisionStatus. */\nexport function mapOutcomeToDecision(outcome: string): VoteDecisionStatus {\n switch (outcome) {\n case 'approved':\n return 'approved';\n case 'rejected':\n return 'rejected';\n case 'timeout':\n return 'timeout';\n default:\n return 'pending';\n }\n}\n\n/**\n * #3587: partial panel degradation — some (but not all) voters errored, so the\n * decision rests on fewer voters than requested. Returns a warning string, or\n * undefined when the panel is full or entirely errored (the latter is already a\n * structured error elsewhere).\n */\nfunction panelDegradationWarning(errorCount: number, total: number): string | undefined {\n if (errorCount <= 0 || errorCount >= total) return undefined;\n return (\n `Panel degraded: ${String(errorCount)} of ${String(total)} voters errored; ` +\n `decision rests on ${String(total - errorCount)} voter(s).`\n );\n}\n\n/** Builds the response from voting result. */\nexport function buildResponse(\n input: ConsensusVoteInput,\n result: ExtendedVotingResult\n): ConsensusVoteResponse {\n const proposalTruncated =\n input.proposal.length > 200 ? input.proposal.slice(0, 200) + '...' : input.proposal;\n\n const errorCount = result.votes.filter((v) => v.source === 'error').length;\n\n const allErrors = errorCount === result.votes.length && errorCount > 0;\n const decision: VoteDecisionStatus =\n !result.result.quorumReached && allErrors\n ? 'no_quorum'\n : mapOutcomeToDecision(result.result.outcome);\n\n const response: ConsensusVoteResponse = {\n proposal: proposalTruncated,\n strategy: result.strategy,\n decision,\n approvalPercentage: result.result.approvalPercentage,\n voteCounts: {\n approve: result.result.voteCounts.approve,\n reject: result.result.voteCounts.reject,\n abstain: result.result.voteCounts.abstain,\n error: errorCount,\n },\n votes: result.votes.map(toAgentVoteSummary),\n durationMs: result.totalTimeMs,\n simulateVotes: result.simulateVotes,\n };\n\n if (input.threshold !== undefined) {\n response.threshold = input.threshold;\n }\n\n if (result.policyReason !== undefined) {\n response.policyReason = result.policyReason;\n }\n\n const panelWarning = panelDegradationWarning(errorCount, result.votes.length);\n if (panelWarning !== undefined) {\n response.panelWarning = panelWarning;\n }\n\n if (isHigherOrderStrategy(result.strategy) && result.higherOrderResult) {\n response.higherOrderMetadata = toHigherOrderMetadata(result.higherOrderResult);\n }\n\n return response;\n}\n\n/** Maps a HigherOrderVotingResult to the response's metadata shape. */\nfunction toHigherOrderMetadata(r: HigherOrderVotingResult): HigherOrderMetadata {\n return {\n posteriorApproval: r.posteriorApproval,\n posteriorRejection: r.posteriorRejection,\n effectiveVoteCount: r.effectiveVoteCount,\n method: r.method,\n usedCorrelationData: r.usedCorrelationData,\n improvementOverBaseline: r.improvementOverBaseline,\n downweightedAgents: r.downweightedAgents,\n reasoning: r.reasoning,\n };\n}\n","/**\n * Error-policy handling for consensus_vote (#2630).\n *\n * When a voter errors or times out (`source === 'error'`), the response\n * shape already distinguishes it via `voteCounts.error` (see\n * consensus-vote-types.ts:188). What was missing: a configurable\n * decision policy for how those error voters interact with the strategy\n * threshold, plus a safety floor for \"too many errors to call a\n * consensus.\"\n *\n * Three policies, plus a hard floor:\n *\n * - `reduce_denominator` (default for non-strict strategies): errors\n * filtered out before the engine sees votes. Denominator = non-error\n * votes. Pragmatic for operational decisions.\n * - `count_as_abstain`: errors reach the engine as abstain. Conservative\n * — error voter is treated as having withheld approval.\n * - `fail_closed` (default for unanimous only, #3138): any error\n * short-circuits to vote-void.\n *\n * Hard floor: if errors > `ERROR_FLOOR_FRACTION` of total voters, the\n * vote always fails regardless of policy. \"All CLIs are down\" is not a\n * consensus.\n *\n * @module mcp/tools/consensus-vote-error-policy\n */\n\nimport type { AgentVoteResult } from '../../cli/vote-types.js';\nimport type { ErrorPolicy } from './consensus-vote-types.js';\nimport { ERROR_FLOOR_FRACTION } from './consensus-vote-types.js';\n\nexport interface ErrorPolicyDecision {\n /** True when the vote should short-circuit to failed without reaching the engine. */\n readonly shortCircuit: boolean;\n /** Human-readable reason when shortCircuit is true. */\n readonly reason?: string;\n /**\n * Votes to feed to the engine. Empty when shortCircuit is true.\n * Otherwise: errors filtered out (`reduce_denominator`) or converted\n * to abstain (`count_as_abstain`).\n */\n readonly engineVotes: readonly AgentVoteResult[];\n}\n\nfunction isHardFloorTripped(errorCount: number, totalCount: number): boolean {\n if (totalCount === 0) return false;\n return errorCount / totalCount > ERROR_FLOOR_FRACTION;\n}\n\n/**\n * Apply the configured error policy to the raw voter list. Returns a\n * decision describing whether the vote should short-circuit and what\n * votes (if any) should reach the consensus engine.\n *\n * The hard floor (`errors / total > ERROR_FLOOR_FRACTION`) takes\n * precedence over any policy — even `reduce_denominator` short-circuits\n * when most voters errored, because the remaining minority isn't a real\n * consensus.\n *\n * The per-voter response list is built from the ORIGINAL `votes` array\n * upstream; this helper only shapes what the engine sees.\n */\nexport function applyErrorPolicy(\n votes: readonly AgentVoteResult[],\n policy: ErrorPolicy\n): ErrorPolicyDecision {\n const errorVotes = votes.filter((v) => v.source === 'error');\n const errorCount = errorVotes.length;\n const totalCount = votes.length;\n\n if (isHardFloorTripped(errorCount, totalCount)) {\n return {\n shortCircuit: true,\n reason: `Errors exceeded ${String(Math.round(ERROR_FLOOR_FRACTION * 100))}% of voters (${String(errorCount)}/${String(totalCount)})`,\n engineVotes: [],\n };\n }\n\n if (policy === 'fail_closed' && errorCount > 0) {\n return {\n shortCircuit: true,\n reason: `fail_closed: ${String(errorCount)} voter(s) errored`,\n engineVotes: [],\n };\n }\n\n if (policy === 'count_as_abstain') {\n // Errors stay in the engine input but as abstain decisions.\n // The original `source: 'error'` is preserved so the per-voter\n // response shape and `voteCounts.error` still report the error.\n return {\n shortCircuit: false,\n engineVotes: votes.map((v) =>\n v.source === 'error' ? { ...v, vote: { ...v.vote, decision: 'abstain' as const } } : v\n ),\n };\n }\n\n // reduce_denominator (default): errors filtered out before engine sees them.\n return {\n shortCircuit: false,\n engineVotes: votes.filter((v) => v.source !== 'error'),\n };\n}\n","/**\n * Persistent OutcomeStore — JSONL-backed cross-session persistence.\n *\n * Extends the in-memory OutcomeStore with disk-backed append-only\n * JSONL storage. Hydrates on construction, appends on every write.\n * Corrupt lines are skipped with a warning (graceful degradation).\n *\n * @module orchestration/outcomes/outcome-store-persistence\n * (Source: Issue #1009 — Cross-session persistence)\n */\n\nimport { appendFileSync, readFileSync, writeFileSync, existsSync } from 'node:fs';\n\nimport type { ILogger } from '../../core/index.js';\nimport { createLogger, getErrorMessage } from '../../core/index.js';\nimport { TaskOutcomeSchema } from './outcome-types.js';\nimport type { TaskOutcome } from './outcome-types.js';\nimport { OutcomeStore, registerPersistentOutcomeStoreFactory } from './outcome-store.js';\nimport type { OutcomeStoreConfig } from './outcome-store.js';\nimport { ensureLearningDir, getOutcomesFile } from '../../config/learning-persistence.js';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface PersistentOutcomeStoreConfig extends OutcomeStoreConfig {\n /** Override the file path (useful for testing). */\n readonly filePath?: string;\n /** Override the data directory (useful for testing). */\n readonly dataDir?: string;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * OutcomeStore that persists entries to a JSONL file on disk.\n *\n * - Construction: hydrates from existing JSONL file (Zod-validates each line)\n * - Append: calls super.append() then appendFileSync one JSON line\n * - Corruption: bad lines are skipped with a warning log\n */\nexport class PersistentOutcomeStore extends OutcomeStore {\n private readonly filePath: string;\n private readonly logger: ILogger;\n\n constructor(config?: PersistentOutcomeStoreConfig, logger?: ILogger) {\n super(config);\n this.filePath = config?.filePath ?? getOutcomesFile();\n this.logger = logger ?? createLogger({ component: 'PersistentOutcomeStore' });\n\n const dataDir = config?.dataDir;\n ensureLearningDir(dataDir);\n this.hydrate();\n this.reclassifyHydrated();\n this.purgeSkippedOnHydrate();\n }\n\n /** Override append to persist each entry to disk. */\n override append(outcome: TaskOutcome): void {\n super.append(outcome);\n this.persistLine(outcome);\n }\n\n // ==========================================================================\n // Private\n // ==========================================================================\n\n /**\n * Reclassify hydrated entries that lack a failureCategory.\n * Bounded: reclassifyAll() skips success outcomes and already-classified\n * entries, so only unclassified failures are processed (#1457).\n */\n /**\n * Purge false failures from skipped workers on hydration (#1528).\n * These are 0ms non-success worker-* entries created before the\n * recording fix, representing routing decisions not real failures.\n */\n private purgeSkippedOnHydrate(): void {\n if (this.size === 0) return;\n const purged = this.purgeSkippedWorkers();\n if (purged > 0) {\n this.logger.info('Purged skipped-worker false failures from history', { purged });\n this.rewriteFile();\n }\n }\n\n private reclassifyHydrated(): void {\n if (this.size === 0) return;\n const reclassified = this.reclassifyAll();\n if (reclassified > 0) {\n this.logger.info('Reclassified hydrated outcomes with updated categories', {\n reclassified,\n });\n this.rewriteFile();\n }\n }\n\n private hydrate(): void {\n if (!existsSync(this.filePath)) {\n this.logger.debug('No outcomes file found, starting fresh', {\n path: this.filePath,\n });\n return;\n }\n\n try {\n const content = readFileSync(this.filePath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim().length > 0);\n let loaded = 0;\n let skipped = 0;\n\n for (const line of lines) {\n try {\n const parsed: unknown = JSON.parse(line);\n const result = TaskOutcomeSchema.safeParse(parsed);\n if (result.success) {\n super.append(result.data);\n loaded++;\n } else {\n skipped++;\n }\n } catch (parseErr: unknown) {\n this.logger.debug('Skipping malformed outcome line during hydration', {\n error: getErrorMessage(parseErr),\n linePreview: line.slice(0, 80),\n });\n skipped++;\n }\n }\n\n this.logger.info('Hydrated outcomes from disk', {\n loaded,\n skipped,\n total: lines.length,\n path: this.filePath,\n });\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n this.logger.warn('Failed to hydrate outcomes from disk', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n\n /** Rewrite the JSONL file from in-memory state after reclassification. */\n private rewriteFile(): void {\n try {\n const entries = this.query();\n const content = entries.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n writeFileSync(this.filePath, content, 'utf-8');\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n this.logger.warn('Failed to rewrite outcomes file after reclassification', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n\n private persistLine(outcome: TaskOutcome): void {\n try {\n appendFileSync(this.filePath, JSON.stringify(outcome) + '\\n', 'utf-8');\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n this.logger.warn('Failed to persist outcome to disk', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n}\n\n// Self-register factory so getOutcomeStore() can create PersistentOutcomeStore\n// without a circular top-level import.\nregisterPersistentOutcomeStoreFactory(() => new PersistentOutcomeStore());\n","/**\n * Consensus Vote — Recording Helpers\n *\n * Memory and outcome store recording for consensus votes.\n * Extracted from consensus-vote.ts for file size compliance.\n *\n * @module mcp/tools/consensus-vote-recording\n * (Source: Issue #753 memory, Issue #1134 cold start)\n */\n\nimport {\n createLogger,\n getErrorMessage,\n getTimeProvider,\n getRandomProvider,\n} from '../../core/index.js';\nimport type { AgentVoteResult } from '../../cli/vote-types.js';\nimport { getToolMemory } from './tool-memory.js';\nimport {\n getOutcomeStore,\n categorizeOutcomeErrorMessage,\n} from '../../orchestration/outcomes/index.js';\nimport {\n DEFAULT_CLI,\n CLI_NAMES,\n type CliNameLiteral,\n} from '../../config/model-capabilities-types.js';\n\nconst logger = createLogger({ tool: 'consensus-vote' });\n\n/**\n * Records a successful consensus vote to session memory AND outcome store. Best-effort.\n *\n * When every vote is simulated, this is a no-op: simulated votes are random\n * (#2319) and must not seed the learning store or outcome store, otherwise\n * test/demo runs poison real routing decisions.\n */\nexport function recordVoteSuccess(\n proposal: string,\n strategy: string,\n outcome: string,\n duration: number,\n votes?: readonly AgentVoteResult[]\n): void {\n const allSimulated =\n votes !== undefined && votes.length > 0 && votes.every((v) => v.source === 'simulation');\n if (allSimulated) {\n logger.debug('Skipping memory + outcome recording — all votes simulated');\n return;\n }\n\n try {\n const memory = getToolMemory();\n memory.recordTask({\n approach: `Consensus vote: ${strategy} on \"${proposal.slice(0, 50)}\"`,\n challenges: [],\n durationMs: duration,\n });\n memory.recordLearning({\n pattern: `${strategy} vote → ${outcome}`,\n context: `proposal=\"${proposal.slice(0, 40)}\" duration=${String(duration)}ms`,\n confidence: 0.8,\n source: 'consensus-vote',\n });\n void memory.runPromotionPipeline().catch((error: unknown) => {\n logger.warn('Promotion pipeline failed', { error });\n });\n } catch (error: unknown) {\n logger.warn('Failed to record vote success to memory', { error: getErrorMessage(error) });\n }\n\n // Also record to outcome store for adaptive routing feedback (#1551).\n // recordVoteOutcomes already filters per-vote `source === 'simulation'`,\n // but we keep the all-simulated guard above to skip the memory writes too.\n if (votes !== undefined) {\n recordVoteOutcomes(votes);\n }\n}\n\n/** Records a failed consensus vote to session memory. Best-effort. */\nexport function recordVoteError(proposal: string, errorMessage: string): void {\n try {\n const memory = getToolMemory();\n memory.recordError({\n error: `Consensus vote failed: ${errorMessage.slice(0, 150)}`,\n solution: 'Pending - vote execution failed',\n filePattern: 'mcp/tools/consensus-vote',\n });\n } catch (error: unknown) {\n logger.warn('Failed to record vote error', { error: getErrorMessage(error) });\n }\n}\n\n/**\n * Records per-vote outcomes to the outcome store for adaptive routing.\n * Each successful LLM vote contributes a sample to its CLI×category pair.\n * (Issue #1134 — cold start mitigation)\n */\nexport function recordVoteOutcomes(votes: readonly AgentVoteResult[]): void {\n try {\n const store = getOutcomeStore();\n const now = new Date().toISOString();\n for (const vote of votes) {\n if (vote.source === 'simulation') continue;\n const cliName: CliNameLiteral =\n vote.cli !== undefined && (CLI_NAMES as readonly string[]).includes(vote.cli)\n ? (vote.cli as CliNameLiteral)\n : DEFAULT_CLI;\n const voteSuccess = vote.source === 'llm';\n store.append({\n id: `vote-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 8)}`,\n cli: cliName,\n category: 'planning',\n model: 'consensus',\n success: voteSuccess,\n durationMs: vote.processingTimeMs,\n timestamp: now,\n source: 'consensus',\n // #2662 — carry the voter role so the stratified outcome report\n // can break consensus results down by role.\n voterRole: vote.role,\n ...(!voteSuccess && vote.error !== undefined\n ? {\n failureCategory: categorizeOutcomeErrorMessage(vote.error),\n errorMessage: vote.error.slice(0, 500),\n }\n : {}),\n });\n }\n } catch (error: unknown) {\n logger.debug('Best-effort vote outcome recording failed', { error: getErrorMessage(error) });\n }\n}\n","/**\n * Consensus → pipeline-bus signal emitter (#3147, epic #3143 P2).\n *\n * Emits the `signal.vote_rejected` observability signal onto the typed pipeline\n * event bus when a consensus vote resolves to `rejected`, closing the\n * self-tuning loop (the shadow TuneStage consumes it). Lives at the MCP\n * integration layer ON PURPOSE: the pure `ConsensusEngine` stays decoupled from\n * the pipeline bus, preserving the `A = observability / B = messaging` boundary\n * adopted for #3289 (scope Option 2 — observability signals route through bus A,\n * the collaboration messaging bus is untouched).\n *\n * @module mcp/tools/consensus-vote-signals\n */\n\nimport { getErrorMessage, getTimeProvider } from '../../core/index.js';\nimport type { ILogger } from '../../core/index.js';\nimport type { ConsensusResult } from '../../consensus/types.js';\nimport type { IEventBus } from '../../pipeline/event-types.js';\n\n/** Distinct rejection categories across the reject votes, or undefined if none. */\nfunction rejectionRulesFrom(result: ConsensusResult): readonly string[] | undefined {\n const rules = new Set<string>();\n for (const vote of result.votes.values()) {\n if (vote.decision === 'reject' && vote.rejectionCategories !== undefined) {\n for (const category of vote.rejectionCategories) rules.add(category);\n }\n }\n return rules.size > 0 ? [...rules] : undefined;\n}\n\n/**\n * Emit `signal.vote_rejected` onto `bus` when `result.outcome === 'rejected'`.\n * No-op for any other outcome. Emission errors are swallowed and logged —\n * observability signalling must never break the vote path.\n */\nexport function emitVoteRejectedSignal(\n result: ConsensusResult,\n bus: IEventBus,\n logger: ILogger\n): void {\n if (result.outcome !== 'rejected') return;\n try {\n const rejectionRules = rejectionRulesFrom(result);\n bus.emit({\n type: 'signal.vote_rejected',\n timestamp: getTimeProvider().now(),\n proposalId: result.proposalId,\n approvalPercentage: result.approvalPercentage,\n ...(rejectionRules !== undefined ? { rejectionRules } : {}),\n });\n } catch (error) {\n logger.warn('Failed to emit signal.vote_rejected', { error: getErrorMessage(error) });\n }\n}\n","/**\n * Simulation Guard — runtime safety net for `simulateVotes: true`.\n *\n * Simulated votes are random and exist only for unit tests and demos.\n * If a caller passes `simulateVotes: true` outside a test runner, this module\n * emits a one-shot stderr warning so the misuse cannot be silent.\n * (Source: Issue #2317, #2319)\n *\n * @module mcp/tools/simulation-guard\n */\n\nimport type { ILogger } from '../../core/index.js';\n\nconst WARNED = new Set<string>();\n\n/** Returns true when running under vitest or another test runner. */\nexport function isTestRunner(): boolean {\n return process.env.VITEST === 'true' || process.env.NODE_ENV === 'test';\n}\n\n/**\n * If `simulate` is true and we are not in a test runner, log a one-shot\n * warning per (tool, process) pair via the supplied logger. Returns the\n * `simulate` value unchanged so it can be used inline.\n *\n * Why: `simulateVotes: true` is a unit-test affordance; using it as a\n * fallback when adapters are unavailable produces random \"decisions\" that\n * silently corrupt downstream behavior. A loud warning is the minimum\n * defense; #2319 also stops simulated runs from polluting tool memory.\n */\nexport function warnIfSimulatedOutsideTests(toolName: string, logger: ILogger): void {\n if (isTestRunner()) return;\n if (WARNED.has(toolName)) return;\n WARNED.add(toolName);\n logger.warn(\n `[${toolName}] simulateVotes=true: output is RANDOM and reserved for tests/demos. Do not treat the result as a real decision.`\n );\n}\n\n/** Test-only: clear the warned-set so repeated tests can re-trigger the warning. */\nexport function _resetWarned(): void {\n WARNED.clear();\n}\n","/**\n * Job-result store for async-mode MCP tools (#3042, Stage 1 of #2631).\n *\n * Persists the final result of a background-dispatched MCP tool\n * invocation to `<NEXUS_DATA_DIR>/jobs/result-<jobId>.json`. Lets a\n * caller dispatch a long-running tool via `mode: 'async'`, receive a\n * `jobId` immediately, and poll for the result via `get_job_result`\n * (or any other reader that imports `readJobResult`).\n *\n * **Why a sidecar file (not the structured-task-state log):** Stage 1\n * deliberately doesn't extend `StructuredTaskState` — that schema change\n * is Stage 2 (#3043). Putting the result in a sidecar file lets the\n * async-mode protocol ship and be validated end-to-end before the schema\n * migration lands. Once Stage 2 ships, this store can be deprecated:\n * `query_task_state` will return the result inline and the sidecar files\n * become legacy that the next cleanup sweep can remove.\n *\n * **Why per-repo storage (`jobs` is in `PER_REPO_SUBDIRS`):** a job\n * dispatched on repo A should not be pollable on repo B. The split\n * matches `tasks/state-orch-*.jsonl` which is also per-repo.\n *\n * Status lifecycle: `pending` → (`complete` | `failed` | `cancelled`).\n * `cancelled` isn't written by Stage 1 (no `cancel_job` yet — that's\n * a follow-up under the same Stage 1 umbrella) but the type space\n * carries it so the next PR doesn't churn the schema.\n *\n * @module mcp/jobs/job-result-store\n */\n\nimport { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';\n\nimport { z } from 'zod';\n\nimport { createLogger } from '../../core/index.js';\nimport { nexusDataPath, nexusDataPathEnsure } from '../../config/nexus-data-dir.js';\n\nconst logger = createLogger({ component: 'job-result-store' });\n\n/** Lifecycle status of a job-result record. */\nexport const JobStatusSchema = z.enum(['pending', 'complete', 'failed', 'cancelled']);\nexport type JobStatus = z.infer<typeof JobStatusSchema>;\n\n/**\n * One on-disk job-result record. Versioned so future readers can\n * tell which Stage wrote it — bump on schema break.\n */\nexport const JobResultSchema = z.object({\n /** Format version. Currently `1` — bump if the shape changes. */\n v: z.literal(1),\n jobId: z.string().min(1),\n /** Tool that was invoked (e.g. `orchestrate`). */\n toolName: z.string().min(1),\n status: JobStatusSchema,\n createdAt: z.iso.datetime(),\n /** Set when the job leaves `pending` — either via `complete` or `failed` or `cancelled`. */\n completedAt: z.iso.datetime().optional(),\n /**\n * Structured payload the synchronous mode would have returned. Present\n * only when `status === 'complete'`. Shape is tool-specific — readers\n * cast to the tool's known output type after status check.\n */\n result: z.unknown().optional(),\n /**\n * Failure message when `status === 'failed'`. Cannot be paired with\n * `result` — the discriminator is `status`.\n */\n error: z.string().optional(),\n});\nexport type JobResult = z.infer<typeof JobResultSchema>;\n\n/** Resolve the sidecar path for a given jobId. */\nfunction jobResultPath(jobId: string): string {\n // `jobs/result-<id>.json` — single segment past `jobs/` so\n // `nexusDataPathEnsure` makes the `jobs/` directory and returns\n // the file path.\n return nexusDataPathEnsure('jobs', `result-${jobId}.json`);\n}\n\n/**\n * Write the initial `pending` record for a new job. Idempotent: if a\n * record for `jobId` already exists (e.g. operator restart re-runs the\n * same idempotencyKey — Stage 1 follow-up), this is a no-op.\n *\n * Caller responsibility: generate a fresh `jobId` per call (Stage 1\n * doesn't yet deduplicate via idempotencyKey — that's #3042 follow-up).\n */\nexport function writeJobPending(jobId: string, toolName: string): void {\n const path = jobResultPath(jobId);\n if (existsSync(path)) {\n logger.debug('Job result file already exists — leaving in place', { jobId });\n return;\n }\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'pending',\n createdAt: new Date().toISOString(),\n };\n writeFileSync(path, JSON.stringify(record, null, 2));\n logger.debug('Wrote pending job record', { jobId, toolName });\n}\n\n/**\n * Replace the record with a terminal `complete` status carrying the\n * structured payload. Caller writes the SAME shape the sync mode would\n * have returned, so a polling client can use the result interchangeably.\n */\nexport function writeJobComplete(jobId: string, toolName: string, result: unknown): void {\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'complete',\n createdAt: readJobResult(jobId)?.createdAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n result,\n };\n writeFileSync(jobResultPath(jobId), JSON.stringify(record, null, 2));\n logger.debug('Wrote complete job record', { jobId, toolName });\n}\n\n/** Terminal `failed` status. `error` is the human-readable failure message. */\nexport function writeJobFailed(jobId: string, toolName: string, error: string): void {\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'failed',\n createdAt: readJobResult(jobId)?.createdAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n error,\n };\n writeFileSync(jobResultPath(jobId), JSON.stringify(record, null, 2));\n logger.debug('Wrote failed job record', { jobId, toolName, error });\n}\n\n/**\n * Terminal `cancelled` status — set by `cancel_job` (#3042 Stage 1b).\n *\n * Idempotent-by-design at the in-memory state level: if the record is\n * already `complete` / `failed` / `cancelled`, `cancel_job` reports\n * `already_complete` / `already_cancelled` to the caller and DOES NOT\n * overwrite the terminal record (per the #3041 vote Security flag —\n * cancel-after-complete must not rewrite history).\n *\n * The caller (cancel_job tool) checks the current status BEFORE calling\n * this; this writer trusts the caller and always overwrites. Guarding\n * here too would duplicate the guard but is cheap insurance — current\n * design: caller-side guard only.\n */\nexport function writeJobCancelled(jobId: string, toolName: string, reason?: string): void {\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'cancelled',\n createdAt: readJobResult(jobId)?.createdAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n ...(reason !== undefined ? { error: reason } : {}),\n };\n writeFileSync(jobResultPath(jobId), JSON.stringify(record, null, 2));\n logger.debug('Wrote cancelled job record', { jobId, toolName, reason });\n}\n\n/**\n * Read a job-result record. Returns `null` if the jobId is unknown\n * (file doesn't exist) or unreadable (corrupt JSON, schema mismatch).\n *\n * Schema mismatch is treated as \"not found\" not \"error\" so a client\n * polling against a future-Stage record from an older nexus-agents\n * process doesn't crash — the request just looks like an unknown jobId\n * until the operator upgrades.\n */\nexport function readJobResult(jobId: string): JobResult | null {\n const path = nexusDataPath('jobs', `result-${jobId}.json`);\n if (!existsSync(path)) return null;\n try {\n const raw = JSON.parse(readFileSync(path, 'utf-8')) as unknown;\n const parsed = JobResultSchema.safeParse(raw);\n if (!parsed.success) {\n logger.warn('Job result file failed schema check', { jobId, path });\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn('Job result file unreadable', {\n jobId,\n path,\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n\n/**\n * List job records under `<NEXUS_DATA_DIR>/jobs/` (#3046 Stage 5).\n *\n * Returns ALL records sorted by `createdAt` descending (newest first).\n * Caller filters by `toolName` / `status` via the `list_jobs` MCP tool —\n * we don't push the filter logic in here because tools change shape but\n * the store doesn't.\n *\n * **The result payloads are intentionally EXCLUDED** from each summary\n * — large complete-status records can be 1 MiB each (per Stage 2's\n * TASK_RESULT_MAX_BYTES cap), and `list_jobs` is meant for discovery,\n * not retrieval. Callers re-fetch full records via `get_job_result(jobId)`.\n *\n * Schema-mismatch + unreadable files are silently dropped (logged as\n * warnings), same policy as `readJobResult`.\n */\nexport interface JobSummary {\n readonly jobId: string;\n readonly toolName: string;\n readonly status: JobResult['status'];\n readonly createdAt: string;\n readonly completedAt?: string;\n /** True iff the record carries an error message (status === 'failed'). */\n readonly hasError: boolean;\n}\n\nexport function listJobs(): JobSummary[] {\n const dir = nexusDataPath('jobs');\n if (!existsSync(dir)) return [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch (err) {\n logger.warn('jobs directory unreadable', {\n dir,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n const summaries: JobSummary[] = [];\n for (const entry of entries) {\n const match = /^result-(.+)\\.json$/.exec(entry);\n if (match === null) continue;\n const jobId = match[1];\n if (jobId === undefined) continue;\n const record = readJobResult(jobId);\n if (record === null) continue;\n const summary: JobSummary = {\n jobId: record.jobId,\n toolName: record.toolName,\n status: record.status,\n createdAt: record.createdAt,\n hasError: record.error !== undefined,\n ...(record.completedAt !== undefined ? { completedAt: record.completedAt } : {}),\n };\n summaries.push(summary);\n }\n // Newest first — matches typical \"what just happened\" discovery flow.\n return summaries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n}\n","/**\n * Idempotency-key resolution for async-mode MCP tool dispatch (#3042 Stage 1c,\n * epic #2631). Lets a caller pass `idempotencyKey: \"<string>\"` and re-invoke\n * the same logical operation safely across sessions / process restarts.\n *\n * ## Contract\n *\n * - Key + matching inputs → returns the existing job's record (whatever\n * state — pending / complete / failed / cancelled). Caller polls\n * `get_job_result(jobId)` exactly as if it had dispatched fresh.\n * - Key + DIFFERENT inputs → fails closed with `idempotency_key_collision`.\n * Reusing a key with different inputs is almost certainly a caller bug;\n * silent merge would either hide a typo or leak the first call's result\n * into a second logical operation.\n * - No key → caller falls back to a fresh `randomUUID()` jobId (existing\n * behavior; this module is a no-op).\n *\n * ## Storage shape\n *\n * One file per (tool, key) tuple at:\n * `<NEXUS_DATA_DIR>/jobs/key-<sha256(tool + ':' + key)>.json`\n *\n * Record: `{ v: 1, tool, key, inputsHash, jobId, createdAt }`.\n *\n * Sharded by `(tool, key)` so two different tools using the same human key\n * don't collide. The filename is the hash so an attacker who reads the\n * directory listing can't recover the user-supplied key.\n *\n * @module mcp/jobs/job-idempotency\n */\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\n\nimport { z } from 'zod';\n\nimport { createLogger } from '../../core/index.js';\nimport { nexusDataPath, nexusDataPathEnsure } from '../../config/nexus-data-dir.js';\n\nconst logger = createLogger({ component: 'job-idempotency' });\n\n/** Index-file record persisted per (tool, key). */\nexport const IdempotencyIndexEntrySchema = z.object({\n v: z.literal(1),\n /** MCP tool name (e.g. `orchestrate`, `run_workflow`, `consensus_vote`). */\n tool: z.string().min(1),\n /** Caller-supplied idempotency key. */\n key: z.string().min(1),\n /** sha256 of the canonical input JSON. */\n inputsHash: z.string().length(64),\n /** Existing jobId for this (tool, key, inputs) tuple. */\n jobId: z.string().min(1),\n /** ISO timestamp of first dispatch. */\n createdAt: z.iso.datetime(),\n});\nexport type IdempotencyIndexEntry = z.infer<typeof IdempotencyIndexEntrySchema>;\n\n/** Outcome of `resolveIdempotency` — discriminated by `kind`. */\nexport type IdempotencyResolution =\n | { readonly kind: 'fresh'; readonly jobId: string }\n | { readonly kind: 'replay'; readonly jobId: string; readonly entry: IdempotencyIndexEntry }\n | {\n readonly kind: 'collision';\n readonly existingInputsHash: string;\n readonly incomingInputsHash: string;\n readonly existingJobId: string;\n };\n\n/** sha256 hex of a string. */\nfunction sha256Hex(input: string): string {\n return createHash('sha256').update(input).digest('hex');\n}\n\n/**\n * Canonical JSON serialization for input hashing. Sorts object keys\n * recursively so `{a:1,b:2}` and `{b:2,a:1}` produce identical hashes.\n *\n * `undefined` values are dropped (JSON semantics); function values throw\n * — schema validation should have caught those upstream.\n */\nfunction canonicalJsonStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonicalJsonStringify).join(',')}]`;\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJsonStringify(v)}`).join(',')}}`;\n}\n\n/** Compute the inputs hash used to detect (tool, key) collisions. */\nexport function computeInputsHash(inputs: unknown): string {\n return sha256Hex(canonicalJsonStringify(inputs));\n}\n\n/** Compute the on-disk index path for a (tool, key) tuple. */\nfunction indexFilePath(tool: string, key: string): string {\n // Filename is hashed so a directory listing doesn't leak user keys.\n const filename = `key-${sha256Hex(`${tool}:${key}`)}.json`;\n return nexusDataPathEnsure('jobs', filename);\n}\n\n/** Read-only counterpart that doesn't create the parent directory. */\nfunction indexFilePathReadOnly(tool: string, key: string): string {\n const filename = `key-${sha256Hex(`${tool}:${key}`)}.json`;\n return nexusDataPath('jobs', filename);\n}\n\n/**\n * Resolve a dispatch request to one of three outcomes:\n *\n * - `fresh`: no prior index entry — caller dispatches a new job using the\n * returned `jobId`, then calls `registerIdempotentJob` to record the\n * index entry. The `jobId` is derived deterministically from\n * `(tool, key, inputsHash)` so concurrent dispatches with the same key\n * converge on the same id and don't double-dispatch.\n * - `replay`: an existing entry has the SAME `inputsHash` — caller skips\n * dispatch and returns the existing job's record (via `readJobResult`).\n * - `collision`: an existing entry has a DIFFERENT `inputsHash` — caller\n * fails closed. Reusing a key with different inputs is a programmer\n * error; silent merge would hide bugs.\n *\n * Callers should NOT call `registerIdempotentJob` when this returns\n * `replay` or `collision` — only on `fresh`.\n */\nexport function resolveIdempotency(\n tool: string,\n idempotencyKey: string | undefined,\n inputs: unknown,\n randomFallback: () => string = randomUUID\n): IdempotencyResolution {\n if (idempotencyKey === undefined || idempotencyKey === '') {\n return { kind: 'fresh', jobId: randomFallback() };\n }\n const incomingInputsHash = computeInputsHash(inputs);\n const path = indexFilePathReadOnly(tool, idempotencyKey);\n if (existsSync(path)) {\n const entry = readIndexEntry(path);\n if (entry !== null) {\n if (entry.inputsHash === incomingInputsHash) {\n return { kind: 'replay', jobId: entry.jobId, entry };\n }\n return {\n kind: 'collision',\n existingInputsHash: entry.inputsHash,\n incomingInputsHash,\n existingJobId: entry.jobId,\n };\n }\n // Index file present but unreadable — treat as fresh, log the breach.\n logger.warn('Idempotency index file unreadable; treating as fresh dispatch', { tool, path });\n }\n // Derive jobId deterministically so two concurrent requests with the\n // same (tool, key, inputs) converge on a single id even if both miss\n // the index lookup race.\n const jobId = `job-${tool}-${sha256Hex(`${tool}:${idempotencyKey}:${incomingInputsHash}`).slice(0, 16)}`;\n return { kind: 'fresh', jobId };\n}\n\n/**\n * Persist the index entry after a `fresh` dispatch. Idempotent — if the\n * file already exists (e.g. a concurrent dispatch raced ahead), the\n * existing entry stays in place. Safe to call without checking\n * `existsSync` first.\n */\nexport function registerIdempotentJob(params: {\n tool: string;\n idempotencyKey: string;\n inputs: unknown;\n jobId: string;\n}): void {\n const path = indexFilePath(params.tool, params.idempotencyKey);\n if (existsSync(path)) {\n logger.debug('Idempotency index entry already present; skipping write', {\n tool: params.tool,\n jobId: params.jobId,\n });\n return;\n }\n const entry: IdempotencyIndexEntry = {\n v: 1,\n tool: params.tool,\n key: params.idempotencyKey,\n inputsHash: computeInputsHash(params.inputs),\n jobId: params.jobId,\n createdAt: new Date().toISOString(),\n };\n writeFileSync(path, JSON.stringify(entry, null, 2));\n logger.debug('Wrote idempotency index entry', { tool: params.tool, jobId: params.jobId });\n}\n\n/**\n * Discriminated outcome of `shortCircuitOrFreshJobId` — `continue` means\n * the caller proceeds with dispatch on `jobId`; `shortCircuit` means the\n * caller returns the envelope `value` immediately and skips dispatch.\n */\nexport type ShortCircuitOutcome<TEnvelope> =\n | { readonly kind: 'continue'; readonly jobId: string }\n | { readonly kind: 'shortCircuit'; readonly value: TEnvelope };\n\n/**\n * One-call wrapper around `resolveIdempotency` that lets each dispatch\n * helper stay under the 50-line cap while keeping the shape of the\n * resulting envelope (toolSuccess / toolStructuredError / errorResponse)\n * tool-specific.\n *\n * Caller supplies:\n * - `replayEnvelope(jobId)` — wraps the per-tool \"replay\" envelope. Most\n * tools return a `{ status: 'replay', jobId, pollTool, note }` JSON\n * string via `toolSuccess`.\n * - `collisionEnvelope(existingJobId)` — wraps the error envelope when\n * the same key was reused with different inputs.\n *\n * On `continue`, the caller MUST call `registerIdempotentJob` after\n * writing the pending record so subsequent replays converge.\n */\nexport function shortCircuitOrFreshJobId<TEnvelope>(params: {\n tool: string;\n idempotencyKey: string | undefined;\n inputs: unknown;\n freshJobId: () => string;\n replayEnvelope: (jobId: string) => TEnvelope;\n collisionEnvelope: (existingJobId: string) => TEnvelope;\n}): ShortCircuitOutcome<TEnvelope> {\n const r = resolveIdempotency(\n params.tool,\n params.idempotencyKey,\n params.inputs,\n params.freshJobId\n );\n if (r.kind === 'collision') {\n return { kind: 'shortCircuit', value: params.collisionEnvelope(r.existingJobId) };\n }\n if (r.kind === 'replay') {\n return { kind: 'shortCircuit', value: params.replayEnvelope(r.jobId) };\n }\n return { kind: 'continue', jobId: r.jobId };\n}\n\n/** Read + schema-validate an index file. Returns `null` on miss / corruption. */\nfunction readIndexEntry(path: string): IdempotencyIndexEntry | null {\n try {\n const raw = JSON.parse(readFileSync(path, 'utf-8')) as unknown;\n const parsed = IdempotencyIndexEntrySchema.safeParse(raw);\n if (!parsed.success) {\n logger.warn('Idempotency index file failed schema check', { path });\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn('Idempotency index file read failed', {\n path,\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n","/**\n * Per-tool async-job concurrency cap (#3044 / epic #2631 Stage 3).\n *\n * Tracks in-flight async-mode dispatches in-process so a noisy caller\n * can't queue 1,000 long-running `run_workflow` invocations behind a\n * slow CLI and exhaust adapter slots. The cap is per-tool (each\n * registered tool gets its own slot count) and per-process — restarting\n * the MCP server resets the count, which is fine because the orphan\n * background promises die with it.\n *\n * Configuration order, lowest priority first:\n * 1. The per-tool default in `DEFAULT_JOB_CAPS` below.\n * 2. Environment override `NEXUS_JOB_MAX_CONCURRENT_<TOOL_UPPER>` —\n * tool name is uppercased + `_` for the env-var match. A value of\n * `0` disables async-mode for that tool entirely (`tryAcquire`\n * always returns busy).\n *\n * The Contrarian-vote flag from #3041 specifically asked for the cap\n * to land BEFORE async-mode expands past `orchestrate` (which has a\n * natural ceiling because it's depth-guarded). This module is the\n * primitive that satisfies that ask for `run_workflow` and later tools.\n *\n * @module mcp/jobs/job-concurrency\n */\n\nimport { createLogger } from '../../core/index.js';\n\nconst logger = createLogger({ component: 'job-concurrency' });\n\n/**\n * Default concurrent-job caps per tool. Numbers are starting points\n * informed by typical workload shape, NOT measured ceilings — re-tune\n * after observing actual job duration distributions in #2703 telemetry.\n *\n * `0` would disable async-mode for that tool; absence means \"no cap\"\n * (currently no tool falls into this category).\n */\nexport const DEFAULT_JOB_CAPS: Readonly<Record<string, number>> = {\n orchestrate: 3,\n run_workflow: 3,\n consensus_vote: 2,\n execute_expert: 4,\n // #3726: run_dev_pipeline is a heavy multi-agent pipeline (plan→vote→\n // decompose→implement→qa→security, each a live LLM call). Cap low — 2\n // concurrent real runs already saturate adapter slots on most hosts.\n run_dev_pipeline: 2,\n // #3730: run_pipeline is a multi-stage adaptive orchestrator with per-stage\n // experts (live LLM calls). Same shape as run_dev_pipeline — cap low at 2.\n run_pipeline: 2,\n // #3731: pr_review fans out to 5 live LLM voters in parallel. Same heavy\n // multi-llm-panel shape as consensus_vote — cap low at 2.\n pr_review: 2,\n // #3731: supply_chain_tradeoff_panel fans out to up to 7 live LLM voters in\n // parallel. Same heavy multi-llm-panel shape as consensus_vote — cap low at 2.\n supply_chain_tradeoff_panel: 2,\n // #3732: execute_spec runs a full spec DAG pipeline (parse→decompose→compile\n // →execute→validate→analyze, live multi-agent execution). Heavy — cap low at 2.\n execute_spec: 2,\n // #3732: run_graph_workflow runs up to ~100 expert nodes with checkpoints.\n // Heavy multi-node pipeline — cap low at 2.\n run_graph_workflow: 2,\n // #3732: run (execute:true) dispatches the heaviest engines (dev-pipeline/\n // pipeline) via the MetaDispatcher. Same heavy-pipeline shape — cap low at 2.\n run: 2,\n};\n\n/**\n * Default total cross-tool cap (defensive backstop, #3046 Stage 5).\n * Per-tool caps prevent a noisy single tool; the global cap prevents\n * 5 tools × 3 jobs each from saturating the host's adapter slots.\n *\n * Env override: `NEXUS_JOB_MAX_CONCURRENT_TOTAL`. Defaults to 10 —\n * comfortably above the sum of per-tool defaults (3+3+2+4=12 is also\n * fine because no realistic workload fills every tool simultaneously)\n * but stops runaway parallel fan-outs.\n */\nexport const DEFAULT_GLOBAL_JOB_CAP = 10;\n\n/** In-flight count per tool. Reset on process restart. */\nconst inFlight = new Map<string, number>();\n\n/** Returns the configured per-tool cap — env override beats default. */\nexport function getJobCap(toolName: string): number {\n const envKey = `NEXUS_JOB_MAX_CONCURRENT_${toolName.toUpperCase()}`;\n const envValue = process.env[envKey];\n if (envValue !== undefined && envValue !== '') {\n const parsed = Number(envValue);\n if (Number.isInteger(parsed) && parsed >= 0) {\n return parsed;\n }\n logger.warn('Invalid env override for job cap — ignoring', {\n tool: toolName,\n envKey,\n envValue,\n });\n }\n return DEFAULT_JOB_CAPS[toolName] ?? DEFAULT_GLOBAL_JOB_CAP;\n}\n\n/**\n * Returns the global cross-tool cap (#3046 Stage 5). Env override:\n * `NEXUS_JOB_MAX_CONCURRENT_TOTAL`. A value of `0` disables async-mode\n * across ALL tools simultaneously.\n */\nexport function getGlobalJobCap(): number {\n const envValue = process.env['NEXUS_JOB_MAX_CONCURRENT_TOTAL'];\n if (envValue !== undefined && envValue !== '') {\n const parsed = Number(envValue);\n if (Number.isInteger(parsed) && parsed >= 0) {\n return parsed;\n }\n logger.warn('Invalid env override for global job cap — ignoring', {\n envKey: 'NEXUS_JOB_MAX_CONCURRENT_TOTAL',\n envValue,\n });\n }\n return DEFAULT_GLOBAL_JOB_CAP;\n}\n\n/** Sum of in-flight counts across all tools (Stage 5 observability). */\nexport function getTotalInFlight(): number {\n let total = 0;\n for (const count of inFlight.values()) total += count;\n return total;\n}\n\n/** Current in-flight count for a tool (testing + observability helper). */\nexport function getInFlight(toolName: string): number {\n return inFlight.get(toolName) ?? 0;\n}\n\n/**\n * Attempt to acquire one slot. Returns `true` on success (caller MUST\n * `release()` exactly once when the job finishes / fails). Returns\n * `false` when EITHER cap is full — per-tool cap OR cross-tool global\n * cap (#3046 Stage 5). Caller responds synchronously with the busy\n * envelope (`{ status: 'busy', retryAfterMs }`).\n *\n * Atomicity note: Node.js is single-threaded between awaits, so this\n * read-then-write pattern is safe as long as no `await` interleaves\n * — and it doesn't here.\n */\nexport function tryAcquire(toolName: string): boolean {\n const cap = getJobCap(toolName);\n // Cap of 0 disables async-mode for the tool.\n if (cap === 0) return false;\n const current = inFlight.get(toolName) ?? 0;\n if (current >= cap) return false;\n // #3046 Stage 5: global cap check. Prevents 5 tools × 3 jobs each\n // saturating adapter slots even when each per-tool cap is satisfied.\n const globalCap = getGlobalJobCap();\n if (globalCap === 0) return false;\n if (getTotalInFlight() >= globalCap) return false;\n inFlight.set(toolName, current + 1);\n return true;\n}\n\n/**\n * Release one slot. Idempotent only in the trivial sense (calling twice\n * is a bug — the counter would underflow). Callers should pair every\n * `tryAcquire` returning `true` with exactly one `release` in a\n * `finally` block to be safe on both success and rejection paths.\n */\nexport function release(toolName: string): void {\n const current = inFlight.get(toolName) ?? 0;\n if (current === 0) {\n logger.warn('release() called with no in-flight count — caller bug', { tool: toolName });\n return;\n }\n inFlight.set(toolName, current - 1);\n}\n\n/**\n * Suggested retry interval for a busy response. Linear in current\n * load — at full cap, suggest 30s; halved as load shrinks. Pure\n * convenience for clients implementing exponential backoff.\n */\nexport function suggestRetryAfterMs(toolName: string): number {\n const cap = getJobCap(toolName);\n if (cap === 0) return 0; // never retry — async-mode is disabled\n const current = inFlight.get(toolName) ?? 0;\n // 30s base, scaled by fullness (clamped to [5s, 60s]).\n const base = 30_000 * (current / Math.max(1, cap));\n return Math.min(60_000, Math.max(5_000, base));\n}\n\n/** Reset all counters. Test-only — do not call from production code. */\nexport function _resetForTests(): void {\n inFlight.clear();\n}\n","/**\n * Shared async-job dispatcher — `runAsJob` (#3729 / epic #2631).\n *\n * Three tools (orchestrate, run_workflow, consensus_vote) implemented the\n * async-mode dispatcher VERBATIM: resolve idempotency → tryAcquire (busy\n * envelope on cap) → writeJobPending → registerIdempotentJob → fire a\n * detached background `run` that writes complete/failed + releases the slot\n * in a `finally` → return a synchronous `{ status: 'pending', jobId }`\n * envelope. This module extracts that sequence once so new long-running\n * tools (run_dev_pipeline, run_pipeline, …) opt into async with a few lines.\n *\n * The dispatcher sequence is FIXED here; the only per-tool variation is the\n * envelope shape (some tools use `ToolResult` via toolSuccess/\n * toolStructuredError, run_workflow uses its structurally-identical\n * `ToolResponse`). Callers that need a non-default envelope supply\n * `toEnvelope`; the default builders reproduce the orchestrate/consensus_vote\n * `ToolResult` envelopes byte-for-byte so faithful migration is a drop-in.\n *\n * @module mcp/jobs/run-as-job\n */\n\nimport type { ILogger } from '../../core/index.js';\nimport { toolSuccess, toolStructuredError, type ToolResult } from '../tools/tool-result.js';\nimport { writeJobComplete, writeJobFailed, writeJobPending } from './job-result-store.js';\nimport { registerIdempotentJob, shortCircuitOrFreshJobId } from './job-idempotency.js';\nimport { release, suggestRetryAfterMs, tryAcquire } from './job-concurrency.js';\nimport { resolveClassGuardMs } from '../../config/timeouts.js';\n\n/**\n * Async-job-body runaway-guard (#3734). A backgrounded job body has NO MCP\n * request timeout (that is the point of async mode), so without a ceiling a\n * wedged `run` would hold its concurrency slot and pending record forever.\n * The `async-job-body` operation class (3600s, honoring NEXUS_TIMEOUT_MULTIPLIER\n * + the per-class override) bounds it. On expiry the job is recorded as failed\n * with `runaway guard exceeded` and the slot is released by the existing\n * `finally`. This is a runaway-guard, not an SLA — 1h is generous.\n */\nexport const ASYNC_JOB_BODY_GUARD_CLASS = 'async-job-body' as const;\n\n/**\n * Fraction of the async-job-body guard at which a near-timeout WARN is emitted\n * before the guard fires. Lower than the generic 0.8 so operators see a wedged\n * long-running job well before the (very high) ceiling trips.\n */\nexport const ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD = 0.5;\n\n/** Sentinel rejection used to distinguish a guard expiry from a body failure. */\nconst ASYNC_JOB_BODY_RUNAWAY_MESSAGE = 'runaway guard exceeded';\n\ninterface GuardHandles {\n /** Resolves only when the guard window elapses (never resolves on clear). */\n readonly expired: Promise<never>;\n /** Cancels the guard + near-timeout timers. */\n readonly clear: () => void;\n}\n\n/**\n * Builds a guard that rejects with the runaway sentinel after `guardMs`, and\n * emits a one-shot near-timeout WARN at {@link ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD}.\n */\nfunction makeAsyncBodyGuard(\n jobId: string,\n toolName: string,\n guardMs: number,\n logger: ILogger | undefined\n): GuardHandles {\n let guardTimer: ReturnType<typeof setTimeout> | undefined;\n let warnTimer: ReturnType<typeof setTimeout> | undefined;\n const expired = new Promise<never>((_resolve, reject) => {\n warnTimer = setTimeout(\n () => {\n logger?.warn(`Async ${toolName} job approaching runaway guard`, {\n jobId,\n guardMs,\n thresholdFraction: ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD,\n });\n },\n Math.floor(guardMs * ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD)\n );\n guardTimer = setTimeout(() => {\n reject(new Error(ASYNC_JOB_BODY_RUNAWAY_MESSAGE));\n }, guardMs);\n // Don't keep the event loop alive solely for these timers.\n guardTimer.unref();\n warnTimer.unref();\n });\n return {\n expired,\n clear: () => {\n if (guardTimer !== undefined) clearTimeout(guardTimer);\n if (warnTimer !== undefined) clearTimeout(warnTimer);\n },\n };\n}\n\n/**\n * Per-tool envelope builders. Every async dispatcher returns the same five\n * logical outcomes; only their wire shape differs. Supplying this lets a tool\n * that uses a different success/error factory (e.g. run_workflow's\n * `successResponse`/`errorResponse`) reuse the dispatcher unchanged.\n *\n * @template E - The tool's MCP envelope type (defaults to {@link ToolResult}).\n */\nexport interface JobEnvelopeBuilders<E> {\n /** `{ status: 'pending', jobId, pollTool, note }` — returned synchronously after dispatch. */\n readonly pending: (jobId: string) => E;\n /** `{ status: 'busy', retryAfterMs, note }` — concurrency cap reached. */\n readonly busy: (retryAfterMs: number, toolName: string) => E;\n /** `{ status: 'replay', jobId, pollTool, note }` — idempotency key matched a prior dispatch. */\n readonly replay: (jobId: string) => E;\n /** Error envelope — idempotency key reused with different inputs. */\n readonly collision: (existingJobId: string) => E;\n}\n\n/** Default pending envelope (orchestrate/consensus_vote shape). */\nexport function defaultPendingEnvelope(jobId: string): ToolResult {\n return toolSuccess(\n JSON.stringify({\n status: 'pending',\n jobId,\n pollTool: 'get_job_result',\n note: 'Poll via get_job_result({ jobId }) until status !== \"pending\".',\n })\n );\n}\n\n/** Default busy envelope (orchestrate/consensus_vote shape). */\nexport function defaultBusyEnvelope(retryAfterMs: number, toolName: string): ToolResult {\n return toolSuccess(\n JSON.stringify({\n status: 'busy',\n retryAfterMs,\n note: `Async-mode concurrency cap reached for ${toolName}. Retry later or use mode: \"sync\".`,\n })\n );\n}\n\n/** Default replay envelope (orchestrate/consensus_vote shape). */\nexport function defaultReplayEnvelope(jobId: string): ToolResult {\n return toolSuccess(\n JSON.stringify({\n status: 'replay',\n jobId,\n pollTool: 'get_job_result',\n note: 'Idempotency key matched a prior dispatch — poll get_job_result for current status.',\n })\n );\n}\n\n/** Default collision envelope (orchestrate/consensus_vote shape). */\nexport function defaultCollisionEnvelope(existingJobId: string): ToolResult {\n return toolStructuredError({\n errorCategory: 'validation',\n message: `Idempotency key already used with different inputs. Existing jobId: ${existingJobId}. Use a fresh key or omit it.`,\n });\n}\n\n/** The full default ({@link ToolResult}) envelope set. */\nexport const DEFAULT_JOB_ENVELOPES: JobEnvelopeBuilders<ToolResult> = {\n pending: defaultPendingEnvelope,\n busy: defaultBusyEnvelope,\n replay: defaultReplayEnvelope,\n collision: defaultCollisionEnvelope,\n};\n\n/**\n * Parameters for {@link runAsJob}.\n *\n * @template I - The tool's validated input type (hashed for idempotency,\n * passed to `run`).\n * @template R - The structured result `run` resolves to; recorded verbatim\n * via `writeJobComplete` and returned by a later `get_job_result(jobId)`.\n * @template E - The tool's envelope type (defaults to {@link ToolResult}).\n */\nexport interface RunAsJobParams<I, R, E = ToolResult> {\n /** MCP tool name — the idempotency / concurrency / job-store key. */\n readonly toolName: string;\n /** Validated tool input. Hashed for idempotency + passed to `run`. */\n readonly input: I;\n /** Caller-supplied idempotency key (optional). */\n readonly idempotencyKey?: string | undefined;\n /** Mints a fresh jobId when no idempotency short-circuit applies. */\n readonly freshJobId: () => string;\n /**\n * The detached background work. Receives the resolved `jobId` (so the\n * runner can thread it into a task-state log) and the `input`. Its\n * resolved value is recorded as the job's `complete` result; a rejection\n * is recorded as `failed`.\n */\n readonly run: (jobId: string, input: I) => Promise<R>;\n /** Per-tool envelope builders. Defaults to the {@link ToolResult} set. */\n readonly toEnvelope?: JobEnvelopeBuilders<E>;\n /** Optional logger for the background failure path. */\n readonly logger?: ILogger | undefined;\n}\n\n/**\n * Dispatch `run` as a detached background job and return a synchronous\n * envelope. Performs the EXACT sequence the three hand-rolled dispatchers\n * shared:\n *\n * 1. Resolve idempotency BEFORE acquiring a slot — a replay/collision must\n * not burn capacity a live caller could use.\n * 2. `tryAcquire(toolName)` — over-cap returns the `busy` envelope.\n * 3. `writeJobPending` + `registerIdempotentJob` (when a key was supplied).\n * 4. Fire-and-forget `run(jobId, input)`: on resolve `writeJobComplete`,\n * on reject `writeJobFailed`, `release` in a `finally`.\n * 5. Return the `pending` envelope (`{ status: 'pending', jobId, … }`).\n *\n * The background promise is intentionally not awaited — async mode exists\n * precisely because awaiting it would defeat the contract. Its rejection is\n * caught + recorded; nothing escapes unhandled.\n *\n * @returns The synchronous envelope: `pending` on dispatch, `busy` on cap,\n * `replay`/`collision` on an idempotency match.\n */\nexport function runAsJob<I, R, E = ToolResult>(params: RunAsJobParams<I, R, E>): E {\n const env = params.toEnvelope ?? (DEFAULT_JOB_ENVELOPES as unknown as JobEnvelopeBuilders<E>);\n\n // Step 1: idempotency resolves BEFORE the slot acquire.\n const idempotency = shortCircuitOrFreshJobId<E>({\n tool: params.toolName,\n idempotencyKey: params.idempotencyKey,\n inputs: params.input,\n freshJobId: params.freshJobId,\n replayEnvelope: env.replay,\n collisionEnvelope: env.collision,\n });\n if (idempotency.kind === 'shortCircuit') return idempotency.value;\n\n // Step 2: per-tool concurrency cap. Over-cap returns busy synchronously.\n if (!tryAcquire(params.toolName)) {\n return env.busy(suggestRetryAfterMs(params.toolName), params.toolName);\n }\n\n const jobId = idempotency.jobId;\n // Step 3: pending record + idempotency index entry.\n writeJobPending(jobId, params.toolName);\n if (params.idempotencyKey !== undefined && params.idempotencyKey !== '') {\n registerIdempotentJob({\n tool: params.toolName,\n idempotencyKey: params.idempotencyKey,\n inputs: params.input,\n jobId,\n });\n }\n\n // Step 4: detached background run with terminal recording + slot release.\n void runJobInBackground(jobId, params);\n\n // Step 5: synchronous pending envelope.\n return env.pending(jobId);\n}\n\n/**\n * Fire-and-forget background runner. Exported (awaitable) so integration\n * tests can drive the dispatch deterministically instead of racing the\n * detached promise.\n * @internal\n */\nexport async function runJobInBackground<I, R, E>(\n jobId: string,\n params: RunAsJobParams<I, R, E>\n): Promise<void> {\n const guardMs = resolveClassGuardMs(ASYNC_JOB_BODY_GUARD_CLASS);\n const guard = makeAsyncBodyGuard(jobId, params.toolName, guardMs, params.logger);\n try {\n // Race the body against the runaway-guard. On guard expiry the guard\n // rejects with the sentinel → recorded as failed below. On body settle the\n // guard is cleared so it can never fire afterward.\n const result = await Promise.race([params.run(jobId, params.input), guard.expired]);\n writeJobComplete(jobId, params.toolName, result);\n } catch (err: unknown) {\n const errObj = err instanceof Error ? err : new Error(String(err));\n params.logger?.error(`Async ${params.toolName} dispatch failed`, errObj, { jobId });\n writeJobFailed(jobId, params.toolName, errObj.message);\n } finally {\n guard.clear();\n release(params.toolName);\n }\n}\n"],"mappings":"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","names":["z","logger","logger","logger","z","z","z","z","z","logger","err","logger","logger","logger","logger","z","logger","z","logger","z","z","appendFileSync","readFileSync","writeFileSync","existsSync","logger","existsSync","readFileSync","writeFileSync","appendFileSync","logger","logger","logger","existsSync","readFileSync","writeFileSync","z","logger","z","existsSync","writeFileSync","readFileSync","err","existsSync","readFileSync","writeFileSync","z","logger","z","existsSync","writeFileSync","readFileSync","err","logger","logger","logger","err","randomUUID","logger","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp/tools/consensus-vote.ts","../src/cli/vote-types.ts","../src/cli-adapters/codex-limits.ts","../src/cli/voter-prompts.ts","../src/cli/voter-response.ts","../src/cli/voter-execution.ts","../src/cli/voter-agents-deadline.ts","../src/cli/voter-agents.ts","../src/consensus/types-voting-protocol.ts","../src/consensus/types-weighted-voting.ts","../src/consensus/higher-order-types.ts","../src/consensus/higher-order-helpers.ts","../src/consensus/higher-order-voting.ts","../src/consensus/strategies.ts","../src/consensus/result-builder.ts","../src/consensus/helpers.ts","../src/consensus/incremental-quorum.ts","../src/consensus/engine.ts","../src/consensus/quorum-validator.ts","../src/consensus/voting-protocol-helpers.ts","../src/consensus/voting-protocol.ts","../src/agents/collaboration/byzantine-events.ts","../src/consensus/weighted-voting-helpers.ts","../src/consensus/weighted-voting.ts","../src/consensus/correlation-helpers.ts","../src/consensus/correlation-tracker.ts","../src/consensus/correlation-persistence.ts","../src/mcp/tools/consensus-vote-types.ts","../src/mcp/tools/consensus-vote-error-policy.ts","../src/orchestration/outcomes/outcome-store-persistence.ts","../src/mcp/tools/consensus-vote-recording.ts","../src/mcp/tools/consensus-vote-signals.ts","../src/mcp/tools/simulation-guard.ts","../src/mcp/jobs/job-result-store.ts","../src/mcp/jobs/job-idempotency.ts","../src/mcp/jobs/job-concurrency.ts","../src/mcp/jobs/run-as-job.ts"],"sourcesContent":["/* eslint-disable max-lines */ // Consensus voting — cohesive single module (governance: 400-600 OK)\n/**\n * nexus-agents/mcp - Consensus Vote Tool\n * @module mcp/tools/consensus-vote\n */\n\nimport { z } from 'zod';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ILogger } from '../../core/index.js';\nimport {\n createLogger,\n getErrorMessage,\n getTimeProvider,\n getRandomProvider,\n formatZodError,\n} from '../../core/index.js';\nimport type { IMcpNotifier } from '../mcp-notifier.js';\nimport { createMcpNotifier, NOOP_NOTIFIER, withProgressHeartbeat } from '../mcp-notifier.js';\nimport {\n wrapToolWithTimeout,\n toSdkCallbackWithBudgetCheck,\n getToolTimeout,\n} from '../middleware/tool-wrapper.js';\nimport { createSecureHandler, type HandlerContext } from '../middleware/secure-handler.js';\nimport {\n toolStructuredError,\n toolSuccess,\n type ToolResult,\n type BaseMcpToolDeps,\n} from './tool-result.js';\nimport type { ConsensusAlgorithm, Vote, ConsensusResult, Proposal } from '../../consensus/types.js';\nimport { SUPERMAJORITY_THRESHOLD } from '../../consensus/types-core.js';\nimport type { VoterRole, AgentVoteResult } from '../../cli/vote-types.js';\nimport { collectRealVotes } from '../../cli/voter-agents.js';\nimport { createConsensusEngine } from '../../consensus/engine.js';\nimport type {\n HigherOrderVotingResult,\n ICorrelationTracker,\n} from '../../consensus/higher-order-types.js';\nimport { HigherOrderVotingStrategy } from '../../consensus/index.js';\nimport {\n createPersistentCorrelationTracker,\n createPersistedProposal,\n saveCorrelationData,\n} from '../../consensus/correlation-persistence.js';\nimport {\n MAX_PROPOSAL_LENGTH,\n VotingStrategySchema,\n VoteThresholdSchema,\n ConsensusVoteInputSchema,\n buildResponse,\n getDefaultErrorPolicy,\n isHigherOrderStrategy,\n shouldEscalateLowPosterior,\n} from './consensus-vote-types.js';\nimport { applyErrorPolicy } from './consensus-vote-error-policy.js';\nimport { recordVoteSuccess, recordVoteError } from './consensus-vote-recording.js';\nimport { emitVoteRejectedSignal } from './consensus-vote-signals.js';\nimport { getPipelineEventBus } from '../../pipeline/event-bus.js';\nimport { warnIfSimulatedOutsideTests } from './simulation-guard.js';\nimport { getToolAnnotations } from '../tool-annotations.js';\n// #3045 / epic #2631 Stage 4 — async-mode dispatch + concurrency cap.\n// #3045 / epic #2631 Stage 4 — async-mode dispatch via the shared `runAsJob`\n// helper (#3729).\nimport { runAsJob } from '../jobs/run-as-job.js';\nimport { randomUUID } from 'node:crypto';\nimport type {\n VotingStrategy,\n ConsensusVoteInput,\n ConsensusVoteResponse,\n ExtendedVotingResult,\n} from './consensus-vote-types.js';\n\nexport type {\n VotingStrategy,\n ConsensusVoteInput,\n ConsensusVoteResponse,\n AgentVoteSummary,\n VoteDecisionStatus,\n HigherOrderMetadata,\n ExtendedVotingResult,\n} from './consensus-vote-types.js';\nexport { VotingStrategySchema, ConsensusVoteInputSchema } from './consensus-vote-types.js';\n\n// --- Correlation Tracker Singleton ---\n//\n// Lifecycle & memory model (documented per #3169):\n// * SCOPE: one process-wide, lazily-created instance shared by every\n// `consensus_vote` call. It accumulates cross-proposal voter agreement so\n// the higher_order strategy can down-weight correlated (redundant) voters.\n// One shared tracker is intentional — correlation signal is only useful\n// pooled across proposals.\n// * PERSISTENCE: backed by `createPersistentCorrelationTracker()`, which\n// hydrates from / appends to the on-disk correlation store, so the signal\n// survives restarts (the in-memory map is a hot cache over that store).\n// * MEMORY BOUND: NOT unbounded. The underlying `CorrelationTracker` is\n// FIFO-bounded by `maxProposals` / `maxObservationsPerAgent` (#521) —\n// oldest proposals are evicted once the cap is hit (eviction is logged at\n// debug in `correlation-tracker.ts`, so memory pressure is observable).\n// * RESET: `resetCorrelationTracker()` drops the instance; the next\n// `getOrCreateCorrelationTracker()` rebuilds it (re-hydrating from disk).\n// Test-isolation only. There is intentionally no per-milestone \"reset\n// between cycles\" coordinator API — eviction already bounds growth, and\n// clearing history mid-run would discard the signal the strategy needs.\nlet persistentCorrelationTracker: ICorrelationTracker | undefined;\n\n/**\n * Gets or creates the process-wide persistent CorrelationTracker (#517).\n * See the lifecycle / memory-bound / reset notes above the declaration (#3169).\n */\nfunction getOrCreateCorrelationTracker(): ICorrelationTracker {\n persistentCorrelationTracker ??= createPersistentCorrelationTracker();\n return persistentCorrelationTracker;\n}\n\n/**\n * Drops the singleton so the next {@link getOrCreateCorrelationTracker} rebuilds\n * it (re-hydrating from the persistent store). Test-isolation only. @internal\n */\nexport function resetCorrelationTracker(): void {\n persistentCorrelationTracker = undefined;\n}\n\n// --- Dependencies ---\nexport interface ConsensusVoteDeps extends BaseMcpToolDeps {\n /** MCP notifier for client-visible logging (Issue #974) */\n notifier?: IMcpNotifier | undefined;\n}\n\n// --- Strategy Resolution ---\nfunction resolveStrategy(input: ConsensusVoteInput): VotingStrategy {\n if (input.strategy !== undefined) return input.strategy;\n if (input.threshold !== undefined) {\n switch (input.threshold) {\n case 'majority':\n return 'simple_majority';\n case 'supermajority':\n return 'supermajority';\n case 'unanimous':\n return 'unanimous';\n }\n }\n return 'simple_majority';\n}\n\nfunction strategyToAlgorithm(strategy: VotingStrategy): ConsensusAlgorithm {\n if (strategy === 'higher_order') return 'higher_order';\n if (strategy === 'opinion_wise') return 'opinion_wise';\n return strategy;\n}\n\nfunction getVoterRoles(quickMode: boolean): readonly VoterRole[] {\n // Default panel expanded to 7 roles 2026-04-25 — scope_steward added to\n // catch build-vs-buy blind spots (#2185). QuickMode substitutes\n // scope_steward for pm so fast triage covers existence-justification.\n return quickMode\n ? ['architect', 'security', 'scope_steward']\n : ['architect', 'security', 'devex', 'ai_ml', 'pm', 'catfish', 'scope_steward'];\n}\n\n// --- Voting Execution ---\n/** Creates a synthetic ConsensusResult when all votes are errors (Issue #815). */\nfunction createEmptyConsensusResult(\n proposal: string,\n algorithm: ConsensusAlgorithm\n): ConsensusResult {\n const now = new Date().toISOString();\n return {\n proposalId: 'no-valid-votes',\n proposal: { title: 'MCP Consensus Vote', description: proposal, algorithm },\n outcome: 'rejected',\n votes: new Map<string, Vote>(),\n voteCounts: { approve: 0, reject: 0, abstain: 0, total: 0 },\n approvalPercentage: 0,\n quorumReached: false,\n startedAt: now,\n closedAt: now,\n durationMs: 0,\n };\n}\n\n/**\n * Creates a synthetic ConsensusResult for an error-policy short-circuit\n * (#2630). Reused for both the hard floor (errors > 50%) and `fail_closed`.\n * Stamps the reason on the proposal title and, since #3124, reports the TRUE\n * vote breakdown of the responding (non-error) voters instead of all-zeros —\n * the outcome stays `rejected` (the policy failed closed), but the counts and\n * `approvalPercentage` are honest (e.g. 6 approvals + 1 error → approve:6,\n * 100%) so callers/audit can see the policy short-circuited a real consensus\n * rather than mistake it for a genuine rejection.\n */\nexport function createPolicyFailedResult(\n proposal: string,\n algorithm: ConsensusAlgorithm,\n reason: string,\n votes: readonly AgentVoteResult[]\n): ConsensusResult {\n const now = new Date().toISOString();\n const voteMap = new Map<string, Vote>();\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n for (const v of votes) {\n if (v.source === 'error') continue; // errors surface separately, not as a decision\n voteMap.set(v.role, v.vote);\n if (v.vote.decision === 'approve') approve++;\n else if (v.vote.decision === 'reject') reject++;\n else abstain++;\n }\n const responding = approve + reject + abstain;\n return {\n proposalId: 'error-policy-short-circuit',\n proposal: { title: `MCP Consensus Vote — ${reason}`, description: proposal, algorithm },\n outcome: 'rejected',\n votes: voteMap,\n voteCounts: { approve, reject, abstain, total: responding },\n approvalPercentage: responding > 0 ? (approve / responding) * 100 : 0,\n quorumReached: false,\n startedAt: now,\n closedAt: now,\n durationMs: 0,\n };\n}\n\n/** Thresholds per algorithm for cascade detection. */\nconst CASCADE_THRESHOLDS: Record<string, number> = {\n majority: 0.5,\n supermajority: SUPERMAJORITY_THRESHOLD,\n unanimous: 1.0,\n};\n\n/** Detect if vote outcome is mathematically decided (#1765). */\nfunction detectEarlyCascade(\n algorithm: string,\n approvals: number,\n rejections: number,\n total: number\n): { decided: boolean; reason: string } {\n const threshold = CASCADE_THRESHOLDS[algorithm] ?? 0.5;\n if (total === 0) return { decided: false, reason: '' };\n\n // Unanimous: any rejection decides\n if (algorithm === 'unanimous' && rejections > 0) {\n return { decided: true, reason: `Unanimous rejected: ${String(rejections)} rejection(s)` };\n }\n // Approval locked: even if all remaining vote reject, approval holds\n if (approvals / total > threshold) {\n return {\n decided: true,\n reason: `Approval locked: ${String(approvals)}/${String(total)} > ${String(threshold)}`,\n };\n }\n // Rejection locked: even if all remaining vote approve, rejection holds\n const remaining = total - approvals - rejections;\n if ((approvals + remaining) / total < threshold) {\n return {\n decided: true,\n reason: `Rejection locked: max possible ${String(approvals + remaining)}/${String(total)} < ${String(threshold)}`,\n };\n }\n return { decided: false, reason: '' };\n}\n\n/**\n * Run the consensus engine over already-policy-applied votes.\n *\n * Callers MUST pass `engineVotes` produced by `applyErrorPolicy` (#2630)\n * — under `reduce_denominator` that means errors are already filtered;\n * under `count_as_abstain` errors have been converted to abstain\n * decisions but kept in the array. This function does no further\n * filtering on `source`.\n */\nasync function processVotesThroughEngine(\n engineVotes: readonly AgentVoteResult[],\n proposal: string,\n algorithm: ConsensusAlgorithm\n): Promise<ConsensusResult> {\n if (engineVotes.length === 0) return createEmptyConsensusResult(proposal, algorithm);\n\n const engine = createConsensusEngine();\n const engineProposal: Proposal = {\n title: 'MCP Consensus Vote',\n description: proposal,\n algorithm,\n };\n const proposalResult = await engine.propose(engineProposal);\n if (!proposalResult.ok)\n throw new Error(`Failed to create proposal: ${proposalResult.error.message}`, {\n cause: proposalResult.error,\n });\n\n const proposalId = proposalResult.value;\n for (const { role, vote } of engineVotes) await engine.vote(proposalId, role, vote);\n\n const resultRes = await engine.close(proposalId);\n if (!resultRes.ok)\n throw new Error(`Failed to close proposal: ${resultRes.error.message}`, {\n cause: resultRes.error,\n });\n return resultRes.value;\n}\n\nfunction runHigherOrderVoting(\n strategy: VotingStrategy,\n voteMap: Map<string, Vote>,\n logger: ILogger\n): HigherOrderVotingResult | undefined {\n if (!isHigherOrderStrategy(strategy)) return undefined;\n const hovStrategy = new HigherOrderVotingStrategy();\n const tracker = getOrCreateCorrelationTracker();\n const result = hovStrategy.aggregate(voteMap, tracker);\n logger.info('Higher-Order Voting complete', {\n method: result.method,\n decision: result.decision,\n posteriorApproval: result.posteriorApproval.toFixed(3),\n });\n return result;\n}\n\nfunction recordVotesToTracker(\n votes: readonly AgentVoteResult[],\n outcome: 'approved' | 'rejected',\n logger: ILogger\n): void {\n // #3170: record the REAL (LLM) votes even when the panel is mixed-source,\n // rather than dropping ALL correlation data because one voter simulated/errored.\n // Recording the accurate LLM-only subset beats leaving the matrix permanently stale.\n const llmVotes = votes.filter((v) => v.source === 'llm');\n if (llmVotes.length < votes.length) {\n logger.warn('Recording only LLM votes to correlation tracker; excluding non-LLM votes', {\n recorded: llmVotes.length,\n excluded: votes.length - llmVotes.length,\n });\n }\n if (llmVotes.length === 0) return; // nothing real to record\n const llmVoteMap = new Map<string, Vote>();\n for (const v of llmVotes) llmVoteMap.set(v.role, v.vote);\n\n const tracker = getOrCreateCorrelationTracker();\n const id = `consensus-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;\n tracker.recordProposalVotes(id, llmVoteMap, outcome);\n logger.debug('Recorded votes to tracker', { proposalId: id, outcome });\n\n try {\n const persisted = createPersistedProposal(id, llmVoteMap, outcome);\n const saveResult = saveCorrelationData([persisted]);\n if (!saveResult.ok) {\n logger.warn('Failed to persist correlation data', { error: saveResult.error.message });\n }\n } catch (error: unknown) {\n const message = getErrorMessage(error);\n logger.warn('Error persisting correlation data', { error: message });\n }\n}\n\n/** Process votes with cascade detection — extracted for max-lines-per-function (#1765). */\n/**\n * Run the engine + cascade-detection + higher-order voting against\n * already-policy-applied votes (#2630).\n *\n * Callers MUST pass `engineVotes` produced by `applyErrorPolicy` — no\n * filtering on `source` happens inside this function. Cascade-detection\n * counts and the higher-order voteMap are both built directly from\n * `engineVotes`.\n */\nasync function processVotesWithCascade(\n engineVotes: readonly AgentVoteResult[],\n opts: {\n totalRoles: number;\n proposal: string;\n algorithm: ConsensusAlgorithm;\n strategy: VotingStrategy;\n log: ILogger;\n }\n): Promise<{\n engineResult: ConsensusResult;\n voteMap: Map<string, Vote>;\n higherOrderResult: ReturnType<typeof runHigherOrderVoting>;\n outcome: 'approved' | 'rejected';\n cascaded: boolean;\n}> {\n const approvals = engineVotes.filter((v) => v.vote.decision === 'approve').length;\n const rejections = engineVotes.filter((v) => v.vote.decision === 'reject').length;\n const cascadeInfo = detectEarlyCascade(opts.algorithm, approvals, rejections, opts.totalRoles);\n\n if (cascadeInfo.decided) {\n opts.log.info('Vote cascade: outcome decided early', {\n approvals,\n rejections,\n total: opts.totalRoles,\n reason: cascadeInfo.reason,\n });\n }\n\n const engineResult = await processVotesThroughEngine(engineVotes, opts.proposal, opts.algorithm);\n const voteMap = new Map<string, Vote>();\n for (const { role, vote } of engineVotes) voteMap.set(role, vote);\n\n const higherOrderResult = cascadeInfo.decided\n ? undefined\n : runHigherOrderVoting(opts.strategy, voteMap, opts.log);\n const outcome: 'approved' | 'rejected' =\n engineResult.outcome === 'approved' ? 'approved' : 'rejected';\n\n return { engineResult, voteMap, higherOrderResult, outcome, cascaded: cascadeInfo.decided };\n}\n\n/** Execute a consensus vote with full strategy support. Exported for pipeline DRY (#1694). */\n/** Confidence threshold above which a contrarian rejection triggers escalation (#1799). */\nconst CONTRARIAN_ESCALATION_THRESHOLD = 0.8;\n\n/** Run a single contrarian agent to check for YAGNI/MISALIGNED/SECURITY_RISK (#1799). */\nasync function runContrarianCheck(\n proposal: string,\n log: ILogger\n): Promise<{ shouldEscalate: boolean; reason: string; confidence: number }> {\n try {\n const { executeExpert } = await import('../../pipeline/expert-bridge.js');\n const prompt = [\n 'You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.',\n 'Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.',\n '',\n `Proposal: ${proposal.slice(0, 2000)}`,\n '',\n 'If you find a strong reason to reject, respond with JSON:',\n '{\"decision\":\"reject\",\"confidence\":0.0-1.0,\"reasoning\":\"your concern\"}',\n 'If the proposal is sound, respond with:',\n '{\"decision\":\"approve\",\"confidence\":0.0-1.0,\"reasoning\":\"why it is acceptable\"}',\n ].join('\\n');\n\n const result = await executeExpert('architecture', prompt);\n if (!result.success) return { shouldEscalate: false, reason: '', confidence: 0 };\n\n const jsonMatch = result.text.match(/\\{[\\s\\S]*\\}/);\n if (jsonMatch === null) return { shouldEscalate: false, reason: '', confidence: 0 };\n\n const parsed = JSON.parse(jsonMatch[0]) as {\n decision?: string;\n confidence?: number;\n reasoning?: string;\n };\n\n const isRejection = parsed.decision === 'reject';\n const confidence = typeof parsed.confidence === 'number' ? parsed.confidence : 0;\n const reasoning = typeof parsed.reasoning === 'string' ? parsed.reasoning : '';\n\n if (isRejection && confidence >= CONTRARIAN_ESCALATION_THRESHOLD) {\n log.info('Contrarian rejected with high confidence', {\n confidence,\n reasoning: reasoning.slice(0, 200),\n });\n return { shouldEscalate: true, reason: reasoning, confidence };\n }\n\n return { shouldEscalate: false, reason: '', confidence };\n } catch (error: unknown) {\n // Closes #2952 (medium): pre-fix the bare `catch {}` swallowed\n // `executeExpert` failures, JSON parse errors, and expert-bridge\n // import errors identically — the escalation guardrail silently\n // disabled itself with no log trail. Log + return the default\n // \"no escalation\" envelope so a contrarian-check infrastructure\n // bug is at least visible in operator logs.\n const message = error instanceof Error ? error.message : String(error);\n log.warn('Contrarian check failed; defaulting to no escalation', { error: message });\n return { shouldEscalate: false, reason: '', confidence: 0 };\n }\n}\n\n/**\n * Build a short-circuit result for the error-policy gate (#2630). Called\n * when the hard floor (>50% errors) trips or `fail_closed` matches.\n * Logs the warning and returns the synthetic `ExtendedVotingResult` that\n * `executeVoting` propagates to the response builder.\n */\nfunction buildPolicyShortCircuitResult(args: {\n input: ConsensusVoteInput;\n strategy: VotingStrategy;\n algorithm: ConsensusAlgorithm;\n votes: readonly AgentVoteResult[];\n errorPolicy: ConsensusVoteInput['errorPolicy'];\n reason: string;\n startTime: number;\n logger: ILogger;\n}): ExtendedVotingResult {\n args.logger.warn('Consensus vote short-circuited by error policy', {\n errorPolicy: args.errorPolicy,\n reason: args.reason,\n });\n const totalTimeMs = getTimeProvider().now() - args.startTime;\n return {\n proposal: args.input.proposal,\n threshold: args.algorithm,\n result: createPolicyFailedResult(args.input.proposal, args.algorithm, args.reason, args.votes),\n votes: args.votes,\n totalTimeMs,\n simulateVotes: args.input.simulateVotes,\n strategy: args.strategy,\n // #3124: surface WHY a high-approval result is still 'rejected' so callers\n // don't mistake a fail-closed policy short-circuit for a genuine rejection.\n policyReason: args.reason,\n };\n}\n\n/**\n * Escalation gate for `quickMode` approvals. Two independent triggers, both\n * re-running `executeVoting` with the full voter panel:\n *\n * 1. Posterior-confidence (#3174): for `higher_order`/`opinion_wise`, a borderline\n * Bayesian posterior (below `HIGHER_ORDER_ESCALATION_POSTERIOR_FLOOR`) means the\n * 3-voter quick panel was barely decisive — escalate without spending a\n * contrarian call. Checked first so a borderline posterior short-circuits it.\n * 2. Contrarian agent (#1799): run a single contrarian to catch\n * YAGNI / SECURITY_RISK / SCOPE_CREEP; escalate if it rejects with high\n * confidence.\n *\n * Returns the escalated result, or `undefined` for \"no escalation, continue\n * with the quickMode result.\"\n */\nasync function maybeEscalateContrarian(\n input: ConsensusVoteInput,\n outcome: 'approved' | 'rejected',\n ctx: { strategy: VotingStrategy; posteriorApproval: number | undefined },\n logger: ILogger,\n opts?: { voteTimeoutMs?: number }\n): Promise<ExtendedVotingResult | undefined> {\n if (!input.quickMode || outcome !== 'approved' || input.simulateVotes) return undefined;\n\n if (shouldEscalateLowPosterior(ctx.strategy, outcome, input.quickMode, ctx.posteriorApproval)) {\n logger.warn('Posterior-confidence escalation: re-running with full vote (#3174)', {\n strategy: ctx.strategy,\n posteriorApproval: ctx.posteriorApproval,\n });\n return executeVoting({ ...input, quickMode: false }, logger, opts);\n }\n\n const escalation = await runContrarianCheck(input.proposal, logger);\n if (!escalation.shouldEscalate) return undefined;\n logger.warn('Contrarian escalation: re-running with full vote', {\n reason: escalation.reason,\n confidence: escalation.confidence,\n });\n return executeVoting({ ...input, quickMode: false }, logger, opts);\n}\n\n/*\n * Top-level voting flow: vote collection → error-policy gate → engine +\n * cascade → contrarian escalation → finalize. Further extraction\n * obscures control flow more than it helps; helpers already extracted\n * are applyErrorPolicy, buildPolicyShortCircuitResult,\n * maybeEscalateContrarian, finalizeVotingResult.\n */\n// eslint-disable-next-line max-lines-per-function -- see block comment above\nexport async function executeVoting(\n input: ConsensusVoteInput,\n logger: ILogger,\n opts?: { voteTimeoutMs?: number }\n): Promise<ExtendedVotingResult> {\n const strategy = resolveStrategy(input);\n const algorithm = strategyToAlgorithm(strategy);\n const roles = getVoterRoles(input.quickMode);\n const startTime = getTimeProvider().now();\n const errorPolicy = input.errorPolicy ?? getDefaultErrorPolicy(strategy);\n\n logger.info('Starting consensus vote', {\n strategy,\n algorithm,\n roleCount: roles.length,\n errorPolicy,\n });\n const votes = await collectRealVotes({\n roles,\n proposal: input.proposal,\n simulate: input.simulateVotes,\n ...(opts?.voteTimeoutMs !== undefined && { timeoutMs: opts.voteTimeoutMs }),\n });\n\n // Error-policy gate (#2630): hard floor + fail_closed + reduce_denominator /\n // count_as_abstain transformation. Engine sees the resulting shape.\n const policyDecision = applyErrorPolicy(votes, errorPolicy);\n if (policyDecision.shortCircuit) {\n return buildPolicyShortCircuitResult({\n input,\n strategy,\n algorithm,\n votes,\n errorPolicy,\n reason: policyDecision.reason ?? 'error policy short-circuit',\n startTime,\n logger,\n });\n }\n\n // Check for early cascade and process votes (#1765)\n const { engineResult, higherOrderResult, outcome, cascaded } = await processVotesWithCascade(\n policyDecision.engineVotes,\n {\n totalRoles: roles.length,\n proposal: input.proposal,\n algorithm,\n strategy,\n log: logger,\n }\n );\n\n recordVotesToTracker(votes, outcome, logger);\n\n const escalated = await maybeEscalateContrarian(\n input,\n outcome,\n { strategy, posteriorApproval: higherOrderResult?.posteriorApproval },\n logger,\n opts\n );\n if (escalated !== undefined) return escalated;\n\n return finalizeVotingResult({\n input,\n strategy,\n algorithm,\n engineResult,\n higherOrderResult,\n votes,\n outcome,\n cascaded,\n startTime,\n logger,\n });\n}\n\n/**\n * Run a consensus vote with a plain goal as the proposal, default settings\n * (real voters, default strategy). The strategy executor the unified `run`\n * entry point dispatches to for the `consensus` strategy (#3575). Non-simulated.\n */\nexport async function runConsensusForGoal(\n goal: string,\n logger: ILogger = createLogger({ tool: 'consensus_vote' })\n): Promise<ExtendedVotingResult> {\n // Parse through the schema so defaults (quickMode, simulateVotes:false) apply.\n return executeVoting(ConsensusVoteInputSchema.parse({ proposal: goal }), logger);\n}\n\n/** Build the final `ExtendedVotingResult` once the engine + cascade settle. */\nfunction finalizeVotingResult(args: {\n input: ConsensusVoteInput;\n strategy: VotingStrategy;\n algorithm: ConsensusAlgorithm;\n engineResult: ConsensusResult;\n higherOrderResult: ReturnType<typeof runHigherOrderVoting>;\n votes: readonly AgentVoteResult[];\n outcome: 'approved' | 'rejected';\n cascaded: boolean;\n startTime: number;\n logger: ILogger;\n}): ExtendedVotingResult {\n const totalTimeMs = getTimeProvider().now() - args.startTime;\n args.logger.info('Consensus vote completed', {\n strategy: args.strategy,\n outcome: args.outcome,\n durationMs: totalTimeMs,\n cascaded: args.cascaded,\n });\n const result: ExtendedVotingResult = {\n proposal: args.input.proposal,\n threshold: args.algorithm,\n result: args.engineResult,\n votes: args.votes,\n totalTimeMs,\n simulateVotes: args.input.simulateVotes,\n strategy: args.strategy,\n };\n if (args.higherOrderResult !== undefined) result.higherOrderResult = args.higherOrderResult;\n return result;\n}\n\n// --- Handler & Registration ---\nasync function handleConsensusVote(\n deps: ConsensusVoteDeps,\n args: ConsensusVoteInput\n): Promise<{ ok: true; value: ConsensusVoteResponse } | { ok: false; error: string }> {\n const logger = deps.logger ?? createLogger({ tool: 'consensus_vote' });\n if (args.simulateVotes) warnIfSimulatedOutsideTests('consensus_vote', logger);\n try {\n const result = await executeVoting(args, logger);\n const strategy = args.strategy ?? 'simple_majority';\n\n // Detect all-error votes: return structured error instead of fake \"rejected\" (#1552)\n const errorVotes = result.votes.filter((v) => v.source === 'error');\n if (errorVotes.length === result.votes.length && result.votes.length > 0) {\n const failures = errorVotes.map((v) => `${v.role}: ${v.error ?? 'unknown error'}`).join('; ');\n logger.warn('All voters failed', { failureCount: errorVotes.length, failures });\n recordVoteError(args.proposal, `All ${String(errorVotes.length)} voters failed: ${failures}`);\n return {\n ok: false,\n error: `All ${String(errorVotes.length)} voters failed. Failures: ${failures}`,\n };\n }\n\n recordVoteSuccess(\n args.proposal,\n strategy,\n result.result.outcome,\n result.totalTimeMs,\n result.votes\n );\n // Close the self-tuning loop: a rejected vote emits signal.vote_rejected\n // onto the typed pipeline bus for the shadow TuneStage (#3147; #3289 Option 2).\n emitVoteRejectedSignal(result.result, getPipelineEventBus(), logger);\n return { ok: true, value: buildResponse(args, result) };\n } catch (error) {\n const message = getErrorMessage(error);\n const cause = error instanceof Error ? error : new Error(message);\n logger.error('Consensus vote failed', cause);\n recordVoteError(args.proposal, message);\n return { ok: false, error: `Voting failed: ${message}` };\n }\n}\n\ntype ConsensusVoteToolResponse = ToolResult;\n\n/**\n * Dispatch the vote on a background promise + return a pending envelope\n * (#3045 / epic #2631 Stage 4). Mirrors run_workflow / orchestrate.\n *\n * Cancellation semantics: when `cancel_job` lands while the vote is\n * in-flight, the existing collector unwinds via the AbortSignal plumbing\n * already in #3038 — `collectRealVotes` honors per-voter signals — and\n * the dispatcher writes whatever partial vote set landed before the\n * abort signal as the job result. That preserves audit visibility into\n * who voted before the cancel happened, instead of throwing away all\n * the work.\n *\n * Concurrency cap is enforced via `tryAcquire('consensus_vote')`\n * (default 2; voting is 7-fan-out so caps multiply adapter load fast).\n */\nfunction dispatchAsyncConsensusVote(\n deps: ConsensusVoteDeps,\n args: import('./consensus-vote-types.js').ConsensusVoteInput\n): ConsensusVoteToolResponse {\n // #3729: dispatch via the shared `runAsJob` helper — the exact sequence this\n // function used to inline. consensus_vote's only diff is the freshJobId; its\n // pending/busy/replay/collision envelopes are byte-for-byte the helper's\n // ToolResult defaults, so no per-tool `toEnvelope` is needed.\n return runAsJob<\n import('./consensus-vote-types.js').ConsensusVoteInput,\n Awaited<ReturnType<typeof handleConsensusVote>>\n >({\n toolName: 'consensus_vote',\n input: args,\n idempotencyKey: args.idempotencyKey,\n freshJobId: () => `job-vote-${randomUUID()}`,\n run: (_jobId, input) => handleConsensusVote(deps, input),\n ...(deps.logger !== undefined ? { logger: deps.logger } : {}),\n });\n}\n\n/**\n * Run the synchronous vote path + format the response. Extracted from\n * the handler so the async-mode branch keeps the per-function size cap\n * (#3045 added a branch + dispatcher call site to the handler).\n */\nasync function runSyncConsensusVote(\n deps: ConsensusVoteDeps,\n notifier: IMcpNotifier,\n args: import('./consensus-vote-types.js').ConsensusVoteInput\n): Promise<ConsensusVoteToolResponse> {\n const result = await withProgressHeartbeat('consensus_vote', notifier, () =>\n handleConsensusVote(deps, args)\n );\n if (!result.ok) {\n return toolStructuredError({ errorCategory: 'internal', message: result.error });\n }\n for (const vote of result.value.votes) {\n notifier.debug('consensus_vote', {\n event: 'vote_collected',\n role: vote.role,\n decision: vote.decision,\n });\n }\n notifier.info('consensus_vote', {\n event: 'vote_complete',\n decision: result.value.decision,\n approvalPercentage: result.value.approvalPercentage,\n voteCount: result.value.votes.length,\n });\n const data = result.value as unknown as Record<string, unknown>;\n return {\n ...toolSuccess(JSON.stringify(result.value, null, 2)),\n structuredContent: data,\n };\n}\n\nfunction createConsensusVoteHandler(deps: ConsensusVoteDeps) {\n const notifier = deps.notifier ?? NOOP_NOTIFIER;\n return async (args: unknown, ctx: HandlerContext): Promise<ConsensusVoteToolResponse> => {\n const validationResult = ConsensusVoteInputSchema.safeParse(args);\n if (!validationResult.success) {\n return toolStructuredError({\n errorCategory: 'validation',\n message: `Validation error: ${formatZodError(validationResult.error)}`,\n });\n }\n const strategy = validationResult.data.strategy ?? 'simple_majority';\n ctx.logger.debug('Starting consensus vote', {\n strategy,\n quickMode: validationResult.data.quickMode,\n ...(validationResult.data.mode !== undefined ? { mode: validationResult.data.mode } : {}),\n });\n notifier.info('consensus_vote', {\n event: 'vote_start',\n proposalLength: validationResult.data.proposal.length,\n strategy,\n });\n // #3045 / epic #2631 Stage 4 — async-mode dispatch.\n if (validationResult.data.mode === 'async') {\n const asyncResult = dispatchAsyncConsensusVote(deps, validationResult.data);\n notifier.info('consensus_vote', {\n event: 'vote_dispatched_async',\n proposalLength: validationResult.data.proposal.length,\n strategy,\n });\n return asyncResult;\n }\n return runSyncConsensusVote(deps, notifier, validationResult.data);\n };\n}\n\n/** Output schema for consensus_vote tool (Issue #1117, #1246). */\nexport const CONSENSUS_VOTE_OUTPUT_SCHEMA = {\n proposal: z.string(),\n strategy: VotingStrategySchema,\n decision: z.enum(['approved', 'rejected', 'no_quorum']),\n approvalPercentage: z.number(),\n voteCounts: z.object({\n approve: z.number(),\n reject: z.number(),\n abstain: z.number(),\n error: z.number(),\n }),\n votes: z.array(\n z.object({\n role: z.string().max(100),\n decision: z.enum(['approve', 'reject', 'abstain']),\n confidence: z.number(),\n reasoning: z.string().max(4000),\n simulated: z.boolean(),\n error: z.boolean(),\n modelUsed: z.string().max(100).optional(),\n rejectionCategories: z\n .array(\n z.enum([\n 'YAGNI',\n 'DRY_VIOLATION',\n 'OVER_ENGINEERING',\n 'SCOPE_CREEP',\n 'SECURITY_RISK',\n 'MISALIGNED',\n 'INSUFFICIENT_EVIDENCE',\n ])\n )\n .optional(),\n })\n ),\n threshold: VoteThresholdSchema.optional(),\n durationMs: z.number(),\n simulateVotes: z.boolean(),\n higherOrderMetadata: z\n .object({\n posteriorApproval: z.number(),\n posteriorRejection: z.number(),\n effectiveVoteCount: z.number(),\n method: z.enum(['ow', 'isp', 'simple']),\n usedCorrelationData: z.boolean(),\n improvementOverBaseline: z.number(),\n downweightedAgents: z.array(z.string().max(100)).max(10),\n reasoning: z.string().max(2000),\n })\n .optional(),\n // #3124: explains a `rejected` decision that coexists with a high\n // approvalPercentage (an error-policy short-circuit, e.g. fail_closed).\n policyReason: z.string().max(200).optional(),\n};\n\n/**\n * Registers the consensus_vote tool with the MCP server.\n * Uses createSecureHandler (Issue #531) with timeout protection (Issue #271).\n * @category MCP\n */\nexport function registerConsensusVoteTool(server: McpServer, deps: ConsensusVoteDeps): void {\n const logger = deps.logger ?? createLogger({ tool: 'consensus_vote' });\n const notifier = deps.notifier ?? createMcpNotifier(server);\n const depsWithNotifier = { ...deps, notifier };\n const toolSchema = {\n proposal: z.string().min(1).max(MAX_PROPOSAL_LENGTH).describe('Proposal text to vote on'),\n threshold: z\n .enum(['majority', 'supermajority', 'unanimous'])\n .optional()\n .describe('Voting threshold (legacy). Use strategy instead.'),\n strategy: VotingStrategySchema.optional().describe(\n 'Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order'\n ),\n quickMode: z.boolean().optional().default(false).describe('Use 3 agents instead of 7'),\n simulateVotes: z\n .boolean()\n .optional()\n .default(false)\n .describe('TESTS ONLY — random output, must not be used for real decisions (#2319)'),\n };\n\n const description =\n 'Execute multi-model consensus voting on a proposal. ' +\n 'Uses 7 specialized agent roles (architect, security, devex, ai_ml, pm, catfish, scope_steward) ' +\n 'to vote on proposals with configurable strategies. ' +\n 'Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514).';\n\n const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {\n toolName: 'consensus_vote',\n rateLimiter: deps.rateLimiter,\n logger,\n });\n\n const timeoutMs = getToolTimeout('consensus_vote', deps.security);\n const wrappedHandler = wrapToolWithTimeout('consensus_vote', secureHandler, {\n timeoutMs,\n logger,\n });\n\n server.registerTool(\n 'consensus_vote',\n {\n description,\n inputSchema: toolSchema,\n outputSchema: CONSENSUS_VOTE_OUTPUT_SCHEMA,\n annotations: getToolAnnotations('consensus_vote'),\n },\n toSdkCallbackWithBudgetCheck(wrappedHandler, 'consensus_vote', timeoutMs, logger)\n );\n logger.info('Registered consensus_vote tool with secure handler and timeout protection');\n}\n","/**\n * nexus-agents vote command types\n *\n * Type definitions for the consensus voting CLI command.\n *\n * (Source: Issue #212, Process Automation Epic #209)\n */\n\nimport type { ConsensusAlgorithm, Vote, ConsensusResult } from '../consensus/types.js';\nimport type { ErrorPolicy, VoteThreshold } from '../mcp/tools/consensus-vote-types.js';\n\n/**\n * Options for the vote command.\n */\nexport interface VoteCommandOptions {\n readonly proposal: string;\n readonly threshold?: VoteThreshold;\n /** Use simulated votes instead of LLM execution (maps from --dry-run CLI flag) */\n readonly dryRun?: boolean;\n readonly quick?: boolean;\n readonly verbose?: boolean;\n readonly createIssue?: boolean;\n readonly issueNumber?: number;\n /** Timeout per vote in milliseconds (default: 90000 per Issue #607) */\n readonly timeoutMs?: number;\n /**\n * How to treat voters that errored or timed out (#2630). When undefined,\n * the same per-strategy default `executeVoting` uses applies:\n * `fail_closed` for unanimous, `reduce_denominator` otherwise.\n */\n readonly errorPolicy?: ErrorPolicy;\n}\n\n/**\n * Voter agent role definitions.\n *\n * `scope_steward` (#2185) was added 2026-04-25 to address a build-vs-buy\n * blind spot in the original 6-role panel: the panel approved a proposal\n * to build a USB-flasher CLI without flagging that Rufus already solves\n * the problem. The scope-steward role explicitly checks for existing tools\n * + biases toward \"don't build.\"\n */\nexport type VoterRole =\n | 'architect'\n | 'security'\n | 'devex'\n | 'ai_ml'\n | 'pm'\n | 'catfish'\n | 'scope_steward';\n\n/**\n * Agent role descriptions for prompt generation.\n */\nexport const VOTER_ROLES: Record<VoterRole, string> = {\n architect: 'Software Architect - evaluates technical design, scalability, and maintainability',\n security:\n 'Security Engineer - evaluates security implications, vulnerabilities, and attack vectors',\n devex: 'Developer Experience - evaluates usability, documentation, and developer workflow',\n ai_ml: 'AI/ML Engineer - evaluates AI/ML aspects, model selection, and learning capabilities',\n pm: 'Product Manager - evaluates business value, user impact, and resource allocation',\n catfish:\n 'Contrarian Analyst - deliberately challenges proposals to prevent agreement bias (arXiv:2505.21503)',\n scope_steward:\n 'Scope Steward - asks whether to build at all; checks existing tools, biases toward kill-the-feature (#2185)',\n};\n\n/**\n * Individual agent vote with metadata.\n */\nexport interface AgentVoteResult {\n readonly role: VoterRole;\n readonly vote: Vote;\n readonly processingTimeMs: number;\n /**\n * Source of the vote:\n * - 'llm': Real LLM execution\n * - 'simulation': Fallback simulation (opt-in only)\n * - 'error': Error during execution (Issue #523)\n */\n readonly source: 'llm' | 'simulation' | 'error';\n /** CLI that executed this vote (for adaptive routing feedback). */\n readonly cli?: string | undefined;\n /** Error message if vote fell back to simulation or encountered an error */\n readonly error?: string;\n}\n\n/**\n * Full voting result.\n */\nexport interface VotingResult {\n readonly proposal: string;\n readonly threshold: ConsensusAlgorithm;\n readonly result: ConsensusResult;\n readonly votes: readonly AgentVoteResult[];\n readonly totalTimeMs: number;\n /** Whether simulated votes were used instead of LLM execution */\n readonly simulateVotes: boolean;\n}\n\n/**\n * Vote verification hash for audit trail.\n */\nexport interface VoteHash {\n readonly role: VoterRole;\n readonly hash: string;\n readonly timestamp: string;\n}\n","/**\n * Codex CLI subagent limits (#2659, Epic D).\n *\n * Codex's `~/.codex/config.toml` `[agents]` section defaults to\n * `max_depth = 1` and `max_threads = 6` (verified against\n * developers.openai.com/codex config reference — the originating issue's\n * `max_thread_depth` key name was wrong).\n *\n * nexus-agents does NOT write the operator's global `~/.codex/config.toml`\n * (that would clobber operator-owned state) and does NOT silently\n * auto-flatten routing topology. Instead — Option C from the #2659 design\n * vote — it WARNS at fan-out time when a planned concurrency would exceed\n * Codex's defaults, so the operator can raise their own `[agents]` limits\n * or spread the panel across more CLIs. The two existing parallel-dispatch\n * sites are already conservative: `worker-dispatcher.ts` caps a wave at 3\n * concurrent workers, and `collectRealVotes` round-robins voter roles\n * across available CLIs. The warned case is the narrow one — a single-CLI\n * fallback where every voter role lands on Codex.\n *\n * @module cli-adapters/codex-limits\n * @see Issue #2659\n */\n\n/** Codex `[agents] max_depth` default — nested subagent depth. */\nexport const CODEX_DEFAULT_MAX_DEPTH = 1;\n\n/** Codex `[agents] max_threads` default — concurrent subagent threads. */\nexport const CODEX_DEFAULT_MAX_THREADS = 6;\n\n/**\n * A structured warning when `codexBoundConcurrency` parallel calls are\n * about to be dispatched to Codex, exceeding its default `max_threads`.\n * Returns `null` when within limits. Does not block — the operator stays\n * in control (Option C).\n */\nexport function checkCodexConcurrency(codexBoundConcurrency: number): string | null {\n if (codexBoundConcurrency <= CODEX_DEFAULT_MAX_THREADS) return null;\n return (\n `${String(codexBoundConcurrency)} parallel calls are bound for Codex, exceeding its ` +\n `default max_threads=${String(CODEX_DEFAULT_MAX_THREADS)}. Codex may queue or drop the ` +\n `excess. Raise [agents] max_threads in ~/.codex/config.toml, or spread the panel across ` +\n `more CLIs (claude/gemini) so fewer roles land on Codex.`\n );\n}\n\n/**\n * A structured warning when a planned subagent nesting `depth` exceeds\n * Codex's default `max_depth`. Returns `null` when within limits.\n */\nexport function checkCodexDepth(depth: number): string | null {\n if (depth <= CODEX_DEFAULT_MAX_DEPTH) return null;\n return (\n `planned subagent nesting depth ${String(depth)} exceeds Codex's default ` +\n `max_depth=${String(CODEX_DEFAULT_MAX_DEPTH)}. Codex will reject the nested spawn. ` +\n `Raise [agents] max_depth in ~/.codex/config.toml, or flatten the expert chain.`\n );\n}\n","/**\n * nexus-agents/cli - Voter System Prompts\n *\n * Role-specific system prompts for voter agents.\n *\n * @module cli/voter-prompts\n * (Source: Issue #226, extracted from voter-agents.ts for #272)\n */\n\nimport type { VoterRole } from './vote-types.js';\n\n/** Default project name used in voter prompts when no context is provided. */\nconst DEFAULT_PROJECT = 'nexus-agents';\n\n/**\n * Generate voter system prompts with optional project context.\n *\n * When nexus-agents MCP tools are used as a service for other projects,\n * the default \"nexus-agents project\" context causes voters to reject\n * proposals as MISALIGNED. This function allows injecting the target\n * project name so voters evaluate correctly.\n *\n * @param project - Project name/context to inject (defaults to 'nexus-agents')\n */\n/**\n * PR-review-mode addendum (#2244). Appended to every voter's prompt so the\n * format is reinforced at the system-prompt level, where role framing\n * dominates — the proposal-text-only approach in #2238 produced 0 verified\n * findings across 50 voter calls in #2241.\n *\n * The addendum is conditional on its face: voters reviewing a non-diff\n * proposal ignore it. Voters reviewing a diff get the explicit format +\n * few-shot example here, plus the same instructions in the proposal text.\n */\nfunction prReviewModeAddendum(): string {\n return `\nPR-review mode — if you are reviewing a code diff (not a proposal) AND you have at least one concrete defect that justifies blocking the merge, populate the OPTIONAL TOP-LEVEL \"findings\" field on your JSON response. NOT inside reasoning — top-level. The schema:\n\n\"findings\": [\n {\n \"summary\": \"One-line summary\",\n \"location\": \"path/file.ext:LINE\",\n \"severity\": \"critical\" | \"high\" | \"medium\" | \"low\",\n \"gate\": {\n \"reread_cited_line\": \"passed\",\n \"traced_call_path\": \"passed\",\n \"named_assertion\": \"Concrete failing assertion — what test would fail and how. Substantive, not 'passed'.\",\n \"ruled_out_language_non_issue\": \"passed\"\n },\n \"claim\": \"What is wrong and why it justifies blocking.\"\n }\n]\n\nA finding only triggers strict request_changes if all 4 gate fields = \"passed\" AND named_assertion is substantive (>10 chars naming a concrete failure, not just \"passed\"). Findings missing any of those surface as informational only — they do not block on their own. The 2026-04-25 audit (#2225) found a 100% false-positive rate when this gate wasn't enforced. If you're approving the diff, OMIT the findings field entirely. If reviewing a non-diff proposal, ignore this section.\n\nHistory note: an earlier prompt asked for YAML inside reasoning; that format was lossy across JSON serialization (#2245). Use the top-level JSON array above.`;\n}\n\n/** Common footer appended to all voter prompts. */\nfunction voterFooter(): string {\n return `\nWorkflow-test assessment (include in your reasoning):\n- Testability: Can changes be verified with automated tests?\n- Workflow integration: Does this fit existing CI/build/test pipelines?\n- Incremental verifiability: Can progress be measured at each step?\n\nWhen rejecting, classify your reasons using categories: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE.\n${prReviewModeAddendum()}`;\n}\n\n/** Build the architect role prompt. */\nfunction architectPrompt(project: string): string {\n return `You are a Software Architect voting on technical proposals for the ${project} project.\n\nYour evaluation criteria:\n- Technical design quality and architectural soundness\n- Scalability and performance implications\n- Maintainability and code organization\n- Alignment with existing patterns (Result<T,E>, Zod validation, TypeScript best practices)\n- Integration complexity with current codebase\n${voterFooter()}\n\nBe direct and technical. Focus on structural implications.`;\n}\n\n/** Build the security role prompt. */\nfunction securityPrompt(project: string): string {\n return `You are a Security Engineer voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- Security vulnerabilities and attack vectors (OWASP Top 10)\n- Input validation and sanitization\n- Secrets management and credential handling\n- Path traversal and injection prevention\n- Rate limiting and resource exhaustion\n${voterFooter()}\n\nBe thorough about risks. Flag any security concerns.`;\n}\n\n/** Build the devex role prompt. */\nfunction devexPrompt(project: string): string {\n return `You are a Developer Experience Engineer voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- API usability and ergonomics\n- Documentation clarity and completeness\n- Learning curve for new developers\n- Testing and debugging experience\n- CLI/tool integration quality\n${voterFooter()}\n\nFocus on practical developer impact.`;\n}\n\n/** Build the AI/ML role prompt. */\nfunction aiMlPrompt(project: string): string {\n return `You are an AI/ML Engineer voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- Multi-agent coordination effectiveness\n- Model selection and routing strategies\n- Context management and token efficiency\n- Learning and adaptation capabilities\n- Consensus protocol design\n- Integration with LLM capabilities\n${voterFooter()}\n\nEvaluate AI/ML implications and opportunities.`;\n}\n\n/** Build the PM role prompt. */\nfunction pmPrompt(project: string): string {\n return `You are a Product Manager voting on proposals for the ${project} project.\n\nYour evaluation criteria:\n- Business value and user impact\n- Resource requirements and timeline\n- Risk assessment and mitigation\n- Priority relative to roadmap\n- Success metrics and validation approach\n- Alignment with project goals in CLAUDE.md\n${voterFooter()}\n\nBalance value against effort. Be pragmatic.`;\n}\n\n/** Build the catfish (contrarian) role prompt. */\nfunction catfishPrompt(project: string): string {\n return `You are a Contrarian Analyst (catfish agent) voting on proposals for the ${project} project.\n\nYour role is to prevent false consensus by deliberately challenging proposals.\nBased on research (arXiv:2505.21503), agreement bias in multi-agent voting leads\nto poor decisions when agents rubber-stamp proposals without genuine scrutiny.\n\nYour evaluation criteria:\n- What are the hidden costs, risks, or downsides not mentioned?\n- What assumptions are being made that might be wrong?\n- What alternatives were not considered?\n- What could go wrong in practice vs. theory?\n- Is there scope creep or unnecessary complexity?\n\nWorkflow-test assessment (include in your reasoning):\n- Testability: Is the proposal verifiable, or just theoretical?\n- Workflow integration: Will this actually work in existing pipelines?\n- Incremental verifiability: Can we tell if it's working at each stage?\n\nWhen rejecting, you MUST classify your reasons using categories: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE.\n\nIMPORTANT: Your job is to find legitimate concerns, not to reject everything.\nIf after genuine scrutiny you find no significant issues, you MAY approve.\nBut your default posture is skeptical — look for what others might miss.\nHigh-confidence rejections with specific reasoning are your most valuable output.\n${prReviewModeAddendum()}`;\n}\n\n/**\n * Build the scope_steward role prompt (#2185).\n *\n * Different axis from `pm` (which prioritizes WHICH features to build) and\n * `catfish` (which doubts the framing). The steward asks: should we build\n * this AT ALL? Existing tools usually win; default bias is \"don't ship.\"\n */\nfunction scopeStewardPrompt(project: string): string {\n return `You are a Scope Steward voting on proposals for the ${project} project.\n\nYour job is to gate against build-when-buy-would-do and feature sprawl.\nThe originating case (2026-04-24): a 6-role panel approved building a USB flasher\nCLI without anyone flagging that Rufus already solves the problem better, for the\nsame audience, with 100M+ installs of battle-tested code. This role exists to\ncatch that class of mistake.\n\nYour evaluation criteria — work through these mandatory checks in your reasoning:\n\n1. **Existing-tool check.** Search your knowledge for tools, libraries, or\n services that already solve the stated problem. Name them concretely\n (not \"there might be alternatives\" — actual names: Rufus, ripgrep,\n esbuild, etc.). If you can't name an alternative, say so explicitly.\n\n2. **Build-vs-buy math.** For each existing tool you named: what would we\n LOSE by adopting it (license, dependency surface, integration cost)?\n What would we GAIN by building our own (tighter integration, no extra\n binary, etc.)? Default lean: BUY. Building is justified only when the\n loss column is concrete and the gain column is load-bearing.\n\n3. **Mission alignment.** Does this proposal serve the project's stated\n mission, or is it scope drift? If drift, name the drift specifically.\n\n4. **Kill-the-feature option.** For every proposal, explicitly evaluate\n \"what if we just didn't do this?\" as a ranked option. Many proposals\n don't need to be built. Make the no-build case before the build case.\n\n5. **Sprawl audit.** Check whether similar functionality already exists\n in the codebase. If it does, recommend extending — not forking. The\n anti-sprawl policy in CLAUDE.md is specifically the rule this role\n enforces.\n\nDefault bias: REJECT proposals where an existing tool fits, even if our\nown implementation would be marginally nicer. Only approve when the\nexisting-tool check fails AND the kill-the-feature option is worse AND\nmission alignment is clear AND no comparable in-codebase functionality\nexists.\n\nFew-shot example of a textbook rejection:\n> Proposal: \"Add an aegis-boot subcommand to flash bootable USB sticks.\"\n> Steward response: \"REJECT (DON'T-BUILD). Rufus has solved this for the\n> same audience for 10+ years with 100M+ installs and battle-tested code.\n> Adopting Rufus loses nothing material; building our own loses\n> maintenance bandwidth indefinitely. Mission alignment: aegis-boot's\n> mission is verifiable boot, not USB tooling. Kill option clearly wins.\n> No prior in-codebase functionality. Recommend: point users at Rufus in\n> the docs and stop here.\"\n\n${voterFooter()}\n\nWhen rejecting, you MUST classify reasons (YAGNI, DRY_VIOLATION,\nOVER_ENGINEERING, SCOPE_CREEP, MISALIGNED). The steward's most common\ncategories are SCOPE_CREEP, YAGNI, and OVER_ENGINEERING.\n\nYou CAN approve. But your default posture is: \"this should not be built;\nprove me wrong with the build-vs-buy math.\"`;\n}\n\nexport function getVoterPrompts(project: string = DEFAULT_PROJECT): Record<VoterRole, string> {\n return {\n architect: architectPrompt(project),\n security: securityPrompt(project),\n devex: devexPrompt(project),\n ai_ml: aiMlPrompt(project),\n pm: pmPrompt(project),\n catfish: catfishPrompt(project),\n scope_steward: scopeStewardPrompt(project),\n };\n}\n\n/**\n * Default prompts (backward compatible — uses 'nexus-agents' project context).\n */\nexport const VOTER_SYSTEM_PROMPTS: Record<VoterRole, string> = getVoterPrompts();\n\n/**\n * Base reasoning templates for simulated votes.\n *\n * scope_steward simulated reasoning intentionally reflects the role's\n * bias-toward-not-shipping posture (PM vote condition on #2185).\n */\nexport const SIMULATED_VOTE_REASONING: Record<VoterRole, string> = {\n architect: 'Evaluated technical design and architecture implications.',\n security: 'Reviewed security considerations and attack surface.',\n devex: 'Assessed developer experience and workflow impact.',\n ai_ml: 'Analyzed AI/ML capabilities and learning potential.',\n pm: 'Evaluated business value and resource requirements.',\n catfish: 'Challenged proposal assumptions and identified potential risks.',\n scope_steward:\n 'Checked existing tools, build-vs-buy math, kill-the-feature option; bias toward not shipping.',\n};\n","/**\n * nexus-agents voter response parsing\n *\n * Schema and parsing utilities for structured vote responses from LLM.\n *\n * (Source: Extracted from voter-agents.ts per Issue #285)\n */\n\nimport { z } from 'zod';\nimport type { Vote } from '../consensus/types.js';\nimport type { VoterRole } from './vote-types.js';\nimport { getErrorMessage, createLogger } from '../core/index.js';\n\n// ============================================================================\n// Error Classes\n// ============================================================================\n\n/**\n * Error thrown when vote response parsing fails and synthetic votes not allowed.\n * (Source: Issue #512 - Fail-safe voting response parsing)\n *\n * By default, parseVoteResponse throws this error when JSON parsing or validation\n * fails. To use synthetic fallback votes (NOT RECOMMENDED), pass\n * `allowSyntheticVote: true` to the options parameter.\n */\nexport class SyntheticVoteError extends Error {\n constructor(\n reason: string,\n public readonly rawOutput: string\n ) {\n super(\n `Vote response parsing failed: ${reason}. ` +\n 'To use synthetic fallback votes (NOT RECOMMENDED), set allowSyntheticVote: true'\n );\n this.name = 'SyntheticVoteError';\n }\n}\n\n/**\n * Vote source tracking - indicates whether vote is real or synthetic.\n * (Source: Issue #512 - Voting integrity)\n */\nexport type ParsedVoteSource = 'parsed' | 'fallback';\n\n/**\n * Extended vote with source tracking.\n */\nexport interface ParsedVote extends Vote {\n readonly source: ParsedVoteSource;\n}\n\n/**\n * Options for parseVoteResponse.\n */\nexport interface ParseVoteOptions {\n /**\n * Allow synthetic fallback votes when parsing fails.\n * Default: false (throws SyntheticVoteError)\n * (Source: Issue #512 - Fail-safe voting)\n */\n readonly allowSyntheticVote?: boolean;\n}\n\n// ============================================================================\n// Structured Vote Response Schema\n// ============================================================================\n\n/**\n * Pre-verified finding shape — voter emits this; downstream\n * `isFindingVerified` adds the derived `verified` flag.\n *\n * #2245 follow-up: voters previously asked to embed YAML findings inside\n * the JSON `reasoning` field. That format is lossy across JSON\n * serialization (backticks/newlines). The v4 retest produced 0 findings\n * across 9 request_changes voters because the LLM either dropped the\n * YAML to keep JSON valid, or produced invalid JSON the parser rejected.\n * Solution: expose findings as a top-level array on the vote response.\n */\nexport const RawFindingSchema = z.object({\n summary: z.string().min(1).max(500).describe('One-line summary of the issue'),\n location: z.string().min(1).max(200).describe('path/file.ext:line'),\n severity: z.enum(['critical', 'high', 'medium', 'low']).default('medium'),\n gate: z.object({\n reread_cited_line: z.enum(['passed', 'failed', 'skipped']).default('skipped'),\n traced_call_path: z.enum(['passed', 'failed', 'skipped']).default('skipped'),\n named_assertion: z\n .string()\n .default('')\n .describe('Concrete failing assertion — substantive, not a rubber-stamp word'),\n ruled_out_language_non_issue: z.enum(['passed', 'failed', 'skipped']).default('skipped'),\n }),\n claim: z.string().min(1).max(2000).describe('What is wrong and why it justifies blocking'),\n});\n\nexport type RawFinding = z.infer<typeof RawFindingSchema>;\n\n/**\n * Zod schema for parsing structured vote responses from LLM.\n */\nexport const VoteResponseSchema = z.object({\n decision: z.enum(['approve', 'reject', 'abstain']).describe('Your vote decision'),\n reasoning: z.string().min(10).max(4000).describe('Explanation for your vote (10-4000 chars)'),\n confidence: z.number().min(0).max(1).describe('Confidence level 0-1'),\n conditions: z.array(z.string()).optional().describe('Optional conditions for approval'),\n /** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */\n rejectionCategories: z\n .array(\n z.enum([\n 'YAGNI',\n 'DRY_VIOLATION',\n 'OVER_ENGINEERING',\n 'SCOPE_CREEP',\n 'SECURITY_RISK',\n 'MISALIGNED',\n 'INSUFFICIENT_EVIDENCE',\n ])\n )\n .optional()\n .describe('Rejection reason categories when decision is reject'),\n /** Top-level structured findings for PR-review mode (#2245 v4 follow-up).\n * Replaces the YAML-in-reasoning encoding that proved lossy. */\n findings: z.array(RawFindingSchema).optional().describe('Structured findings (PR review only)'),\n});\n\nexport type VoteResponse = z.infer<typeof VoteResponseSchema>;\n\n/**\n * Hand-authored JSON Schema mirroring {@link VoteResponseSchema} (#3433).\n *\n * Used as the `input_schema` for a forced Claude `tool_use` call so the\n * ClaudeAdapter can honor `responseFormat: { type: 'json_schema' }` for votes.\n * `zod-to-json-schema` is intentionally NOT a dependency — this object is the\n * single source of truth for the JSON-Schema view of a vote response.\n *\n * Drift between this and `VoteResponseSchema` is caught by the contract test\n * in `voter-response.test.ts` (every Zod key must appear here and vice-versa).\n */\nexport const VOTE_JSON_SCHEMA: Record<string, unknown> = {\n type: 'object',\n additionalProperties: false,\n required: ['decision', 'reasoning', 'confidence'],\n properties: {\n decision: {\n type: 'string',\n enum: ['approve', 'reject', 'abstain'],\n description: 'Your vote decision',\n },\n reasoning: {\n type: 'string',\n minLength: 10,\n maxLength: 4000,\n description: 'Explanation for your vote (10-4000 chars)',\n },\n confidence: {\n type: 'number',\n minimum: 0,\n maximum: 1,\n description: 'Confidence level 0-1',\n },\n conditions: {\n type: 'array',\n items: { type: 'string' },\n description: 'Optional conditions for approval',\n },\n rejectionCategories: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'YAGNI',\n 'DRY_VIOLATION',\n 'OVER_ENGINEERING',\n 'SCOPE_CREEP',\n 'SECURITY_RISK',\n 'MISALIGNED',\n 'INSUFFICIENT_EVIDENCE',\n ],\n },\n description: 'Rejection reason categories when decision is reject',\n },\n findings: {\n type: 'array',\n description: 'Structured findings (PR review only)',\n items: {\n type: 'object',\n additionalProperties: false,\n required: ['summary', 'location', 'severity', 'gate', 'claim'],\n properties: {\n summary: {\n type: 'string',\n minLength: 1,\n maxLength: 500,\n description: 'One-line summary of the issue',\n },\n location: {\n type: 'string',\n minLength: 1,\n maxLength: 200,\n description: 'path/file.ext:line',\n },\n severity: { type: 'string', enum: ['critical', 'high', 'medium', 'low'] },\n gate: {\n type: 'object',\n additionalProperties: false,\n required: [\n 'reread_cited_line',\n 'traced_call_path',\n 'named_assertion',\n 'ruled_out_language_non_issue',\n ],\n properties: {\n reread_cited_line: { type: 'string', enum: ['passed', 'failed', 'skipped'] },\n traced_call_path: { type: 'string', enum: ['passed', 'failed', 'skipped'] },\n named_assertion: {\n type: 'string',\n description: 'Concrete failing assertion — substantive, not a rubber-stamp word',\n },\n ruled_out_language_non_issue: {\n type: 'string',\n enum: ['passed', 'failed', 'skipped'],\n },\n },\n },\n claim: {\n type: 'string',\n minLength: 1,\n maxLength: 2000,\n description: 'What is wrong and why it justifies blocking',\n },\n },\n },\n },\n },\n};\n\n// ============================================================================\n// Vote Prompt Construction\n// ============================================================================\n\n/** Example responses appended to vote prompts. Kept as a constant to keep\n * `buildVotePrompt` under the max-lines-per-function lint cap. */\nconst VOTE_PROMPT_EXAMPLES = `Example approve response:\n{\n \"decision\": \"approve\",\n \"reasoning\": \"The proposal aligns with architectural patterns. Testability: high — unit tests can verify each component. Workflow integration: fits existing CI pipeline.\",\n \"confidence\": 0.85,\n \"conditions\": [\"Add unit tests before merge\"]\n}\n\nExample reject response:\n{\n \"decision\": \"reject\",\n \"reasoning\": \"This adds speculative abstractions for hypothetical future needs. Testability: unclear — no concrete test plan provided.\",\n \"confidence\": 0.80,\n \"rejectionCategories\": [\"YAGNI\", \"OVER_ENGINEERING\"]\n}\n\nExample PR-review request_changes response with structured findings:\n{\n \"decision\": \"reject\",\n \"reasoning\": \"Off-by-one in clampPageSize and missing null guard on response.timing — both visible in the diff.\",\n \"confidence\": 0.9,\n \"rejectionCategories\": [\"INSUFFICIENT_EVIDENCE\"],\n \"findings\": [\n {\n \"summary\": \"Off-by-one in clampPageSize\",\n \"location\": \"packages/nexus-agents/src/api/pagination.ts:18\",\n \"severity\": \"high\",\n \"gate\": {\n \"reread_cited_line\": \"passed\",\n \"traced_call_path\": \"passed\",\n \"named_assertion\": \"Test would assert clampPageSize(50, 100) === 50; this returns 49.\",\n \"ruled_out_language_non_issue\": \"passed\"\n },\n \"claim\": \"Function name says 'clamp to range' but returns requested-1 in the in-range path.\"\n }\n ]\n}`;\n\n/**\n * Constructs the user prompt for vote evaluation.\n * Includes workflow-test evaluation criteria (Issue #1212) and\n * rejection category instructions (Issue #1213).\n */\nexport function buildVotePrompt(proposal: string): string {\n return `Evaluate the following proposal and provide your vote.\n\nPROPOSAL:\n${proposal}\n\nIn addition to your role-specific criteria, assess these workflow-test dimensions:\n- Testability: Can the proposed changes be verified with automated tests?\n- Workflow integration: Does this fit into existing CI/make/test workflows?\n- Incremental verifiability: Can progress be measured at each step?\n\nRespond with a JSON object containing:\n- decision: \"approve\", \"reject\", or \"abstain\"\n- reasoning: Explanation for your vote (10-4000 characters). Include your workflow-test assessment.\n- confidence: Number between 0 and 1\n- conditions: Optional array of conditions for approval\n- rejectionCategories: Required when rejecting. Array of categories from: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE\n- findings: PR-REVIEW MODE ONLY. Optional top-level array of structured findings — see \"PR-review mode\" in the system prompt. OMIT this field entirely when reviewing a non-diff proposal or when approving a diff.\n\n${VOTE_PROMPT_EXAMPLES}`;\n}\n\n// ============================================================================\n// Vote Response Parsing\n// ============================================================================\n\n/**\n * Extracts JSON from LLM response text.\n * Handles responses that may include markdown code blocks.\n */\nexport function extractJsonFromResponse(text: string): string {\n // Try to find JSON in code blocks first\n const codeBlockMatch = /```(?:json)?\\s*([\\s\\S]*?)```/i.exec(text);\n if (codeBlockMatch?.[1] !== undefined) {\n return codeBlockMatch[1].trim();\n }\n\n // Look for JSON object directly\n const jsonMatch = /\\{[\\s\\S]*\\}/i.exec(text);\n if (jsonMatch?.[0] !== undefined) {\n return jsonMatch[0];\n }\n\n return text.trim();\n}\n\n/**\n * Creates a fallback vote when parsing fails.\n * Attempts to infer decision from text content.\n * ONLY used when allowSyntheticVote is explicitly true.\n * (Source: Issue #512 - Fail-safe voting)\n */\nfunction createFallbackVote(output: string, _role: VoterRole, reason: string): ParsedVote {\n const lower = output.toLowerCase();\n let decision: Vote['decision'] = 'abstain';\n\n // Simple keyword detection - heuristic only\n // Check reject keywords FIRST since \"disagree\" contains \"agree\" substring\n if (lower.includes('reject') || lower.includes('decline') || lower.includes('disagree')) {\n decision = 'reject';\n } else if (lower.includes('approve') || lower.includes('accept') || lower.includes('agree')) {\n decision = 'approve';\n }\n\n // Log warning about synthetic vote\n createLogger({ component: 'voter-response' }).warn(\n 'Creating synthetic vote (NOT parsed from LLM output)',\n { decision, reason }\n );\n\n return {\n decision,\n reasoning: `[SYNTHETIC: ${reason}] ${output.slice(0, 200)}`,\n confidence: 0.5,\n source: 'fallback', // Mark as synthetic\n };\n}\n\n/** Maps a validated VoteResponse into a ParsedVote, threading optional fields. */\nfunction buildParsedVote(data: VoteResponse): ParsedVote {\n return {\n decision: data.decision,\n reasoning: data.reasoning,\n confidence: data.confidence,\n ...(data.conditions !== undefined ? { conditions: data.conditions } : {}),\n ...(data.rejectionCategories !== undefined\n ? { rejectionCategories: data.rejectionCategories }\n : {}),\n ...(data.findings !== undefined ? { findings: data.findings } : {}),\n source: 'parsed',\n };\n}\n\n/**\n * Parses vote response from LLM output.\n *\n * By default, throws SyntheticVoteError if parsing fails. To use synthetic\n * fallback votes (NOT RECOMMENDED), pass `allowSyntheticVote: true`.\n *\n * (Source: Issue #512 - Fail-safe voting response parsing)\n *\n * @param output - Raw LLM output text\n * @param role - Voter role for context\n * @param options - Parsing options including allowSyntheticVote\n * @returns ParsedVote with source tracking\n * @throws SyntheticVoteError if parsing fails and allowSyntheticVote is false\n */\nexport function parseVoteResponse(\n output: string,\n role: VoterRole,\n options?: ParseVoteOptions\n): ParsedVote {\n const allowSyntheticVote = options?.allowSyntheticVote ?? false;\n\n try {\n const jsonStr = extractJsonFromResponse(output);\n const parsed = JSON.parse(jsonStr) as unknown;\n const validated = VoteResponseSchema.safeParse(parsed);\n\n if (validated.success) {\n return buildParsedVote(validated.data);\n }\n\n // Validation failed - throw or fallback based on config\n const reason = `Validation failed: ${validated.error.issues.map((e: { message: string }) => e.message).join(', ')}`;\n if (!allowSyntheticVote) {\n throw new SyntheticVoteError(reason, output);\n }\n return createFallbackVote(output, role, reason);\n } catch (error) {\n // If it's already a SyntheticVoteError, rethrow it\n if (error instanceof SyntheticVoteError) {\n throw error;\n }\n\n // Parse error - throw or fallback based on config\n const reason = getErrorMessage(error, 'Unknown parse error');\n if (!allowSyntheticVote) {\n throw new SyntheticVoteError(reason, output);\n }\n return createFallbackVote(output, role, reason);\n }\n}\n","/**\n * nexus-agents voter execution utilities\n *\n * Vote execution helpers including result creation, timeout handling,\n * retry logic, and simulation fallback.\n *\n * (Source: Extracted from voter-agents.ts per Issue #285)\n */\n\nimport type { Vote } from '../consensus/types.js';\nimport type { VoterRole, AgentVoteResult } from './vote-types.js';\nimport type { IModelAdapter, CompletionRequest, ILogger } from '../core/index.js';\nimport { getRandomProvider } from '../core/index.js';\nimport { delay, withTimeout } from '../utils/async-utils.js';\nimport { VOTER_SYSTEM_PROMPTS, SIMULATED_VOTE_REASONING } from './voter-prompts.js';\nimport {\n buildVotePrompt,\n parseVoteResponse,\n SyntheticVoteError,\n VOTE_JSON_SCHEMA,\n} from './voter-response.js';\n\n// Import timeout constants from canonical source (Issue #984)\nimport {\n VOTE_TIMEOUTS,\n resolveVoteTimeout as _resolveVoteTimeout,\n validateTimeout as _validateTimeout,\n} from '../config/timeouts.js';\n\n/** Default vote timeout. Canonical source: `config/timeouts.ts`. */\nexport const DEFAULT_VOTE_TIMEOUT_MS = VOTE_TIMEOUTS.defaultMs;\n\n/** Resolves vote timeout with env var override. Canonical: `config/timeouts.ts`. */\nexport const resolveVoteTimeout = _resolveVoteTimeout;\n\n/** Maximum vote timeout. Canonical source: `config/timeouts.ts`. */\nexport const MAX_VOTE_TIMEOUT_MS = VOTE_TIMEOUTS.maxMs;\n\n/** Minimum vote timeout. Canonical source: `config/timeouts.ts`. */\nexport const MIN_VOTE_TIMEOUT_MS = VOTE_TIMEOUTS.minMs;\n\n/** Maximum retries per vote. Canonical source: `config/timeouts.ts`. */\nexport const DEFAULT_MAX_RETRIES = VOTE_TIMEOUTS.maxRetries;\n\n/**\n * Initial retry delay in milliseconds.\n */\nconst INITIAL_RETRY_DELAY_MS = 1_000;\n\n/**\n * Retry delay for rate-limit errors in milliseconds (Issue #1319).\n * Longer than standard to respect API rate limits.\n */\nexport const RATE_LIMIT_RETRY_DELAY_MS = 5_000;\n\n/**\n * Detects whether an error message indicates a rate-limit condition.\n * Delegates to canonical rate-limit-detector (DRY consolidation Issue #1596).\n */\nimport { isRateLimitLikeError } from '../adapters/rate-limit-detector.js';\n\n/** @see isRateLimitLikeError — re-exported for backward compatibility */\nexport function isRateLimitError(message: string): boolean {\n return isRateLimitLikeError(new Error(message));\n}\n\n/**\n * Validates and clamps timeout to `[VOTE_TIMEOUTS.minMs, VOTE_TIMEOUTS.maxMs]`.\n *\n * **Canonical source:** `config/timeouts.ts`. This re-export exists for\n * back-compat — new code should import from `../config/timeouts.js`\n * directly (#2637).\n */\nexport const validateTimeout = _validateTimeout;\n\n// ============================================================================\n// Vote Result Helpers\n// ============================================================================\n\n/**\n * Creates an error vote result (abstain with error message).\n * Issue #523: Uses source: 'error' instead of 'llm' for accuracy.\n */\nexport function createErrorVoteResult(\n role: VoterRole,\n errorMsg: string,\n processingTimeMs: number\n): AgentVoteResult {\n return {\n role,\n vote: {\n decision: 'abstain',\n reasoning: `[Error] Vote execution failed: ${errorMsg}`,\n confidence: 0,\n },\n processingTimeMs,\n source: 'error',\n error: errorMsg,\n };\n}\n\n/**\n * Creates a simulation vote result.\n */\nexport function createSimulationVoteResult(\n role: VoterRole,\n proposal: string,\n processingTimeMs: number,\n error?: string\n): AgentVoteResult {\n return {\n role,\n vote: simulateVote(role, proposal),\n processingTimeMs,\n source: 'simulation',\n ...(error !== undefined && { error }),\n };\n}\n\n/**\n * Creates simulated votes for multiple roles.\n */\nexport function createSimulatedVotes(\n roles: readonly VoterRole[],\n proposal: string,\n error?: string\n): readonly AgentVoteResult[] {\n const random = getRandomProvider();\n return roles.map((role) =>\n createSimulationVoteResult(role, proposal, random.randomInt(0, 100), error)\n );\n}\n\n/**\n * Role-specific vote distributions for simulation.\n * Each role has weighted probabilities reflecting their typical concerns:\n * - security: More skeptical, finds potential issues\n * - architect: Technically focused, generally supportive of good design\n * - devex: Balanced, considers usability\n * - ai_ml: Technically focused, evaluates AI aspects\n * - pm: Business focused, generally supportive of value\n *\n * Format: [approve_weight, reject_weight, abstain_weight]\n */\nconst ROLE_VOTE_DISTRIBUTIONS: Record<VoterRole, [number, number, number]> = {\n security: [40, 45, 15], // More skeptical - security concerns\n architect: [55, 30, 15], // Generally approving of good design\n devex: [50, 30, 20], // Balanced - considers usability\n ai_ml: [55, 30, 15], // Technical focus\n pm: [55, 25, 20], // Business focus - generally supportive\n catfish: [20, 65, 15], // Deliberately contrarian - challenges proposals (arXiv:2505.21503)\n scope_steward: [25, 60, 15], // Default-bias toward not shipping (#2185)\n};\n\n/**\n * Selects a decision based on weighted probabilities.\n */\nfunction selectWeightedDecision(\n weights: [number, number, number]\n): 'approve' | 'reject' | 'abstain' {\n const random = getRandomProvider();\n const total = weights[0] + weights[1] + weights[2];\n const rand = random.random() * total;\n\n if (rand < weights[0]) return 'approve';\n if (rand < weights[0] + weights[1]) return 'reject';\n return 'abstain';\n}\n\n/**\n * Fallback simulation when LLM is unavailable.\n * Uses role-specific vote distributions to provide more realistic simulation.\n * Clearly marks output as simulated.\n *\n * (Improved per Issue #453 - remove hardcoded 60% approve bias)\n */\nexport function simulateVote(role: VoterRole, proposal: string): Vote {\n const random = getRandomProvider();\n const weights = ROLE_VOTE_DISTRIBUTIONS[role];\n const decision = selectWeightedDecision(weights);\n\n // Confidence varies by decision type and role\n // Rejections tend to be higher confidence (found specific issue)\n // Approvals are moderate confidence (no issues found, but limited analysis)\n // Abstains are low confidence (insufficient information)\n let baseConfidence: number;\n if (decision === 'reject') {\n baseConfidence = 0.6 + random.random() * 0.3; // 0.6-0.9\n } else if (decision === 'approve') {\n baseConfidence = 0.5 + random.random() * 0.3; // 0.5-0.8\n } else {\n baseConfidence = 0.3 + random.random() * 0.2; // 0.3-0.5\n }\n\n return {\n decision,\n reasoning: `[Simulated - no LLM available] ${SIMULATED_VOTE_REASONING[role]} Proposal: \"${proposal.slice(0, 50)}...\"`,\n confidence: baseConfidence,\n };\n}\n\n// ============================================================================\n// Timeout and Retry Utilities\n// ============================================================================\n\n// Re-export from canonical source for backward compatibility\nexport { withTimeout, delay } from '../utils/async-utils.js';\n\n// ============================================================================\n// Vote Attempt Execution\n// ============================================================================\n\n/**\n * Extracts text content from completion response.\n */\nexport function extractTextFromResponse(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .map((block) => {\n if (typeof block === 'object' && block !== null && 'type' in block) {\n const typed = block as { type: string; text?: string };\n if (typed.type === 'text' && typeof typed.text === 'string') {\n return typed.text;\n }\n }\n return '';\n })\n .join('');\n }\n return String(content);\n}\n\n/**\n * Executes a single vote attempt (no retries).\n *\n * By default, throws SyntheticVoteError if response parsing fails.\n * This ensures we only get real LLM votes, not synthetic fallbacks.\n * (Source: Issue #512 - Fail-safe voting)\n */\n/**\n * Builds the vote completion request. `withResponseFormat` toggles the native\n * structured-output ask (#3433): on for the first attempt, off for the #3497\n * retry against backends that route `json_schema` through provider tool-use.\n * The `parseVoteResponse` regex/Zod path below accepts prose-wrapped JSON, so\n * omitting `responseFormat` is safe — it just loses the schema-enforced shape.\n */\nfunction buildVoteRequest(\n role: VoterRole,\n proposal: string,\n timeoutMs: number,\n withResponseFormat: boolean\n): CompletionRequest {\n const base: CompletionRequest = {\n messages: [\n { role: 'system', content: VOTER_SYSTEM_PROMPTS[role] },\n { role: 'user', content: buildVotePrompt(proposal) },\n ],\n // 2000 (#2245): JSON envelope + reasoning + YAML findings exceed the old 500.\n maxTokens: 2000,\n temperature: 0.3, // Low temperature for consistent evaluations\n // Thread the vote budget so the CLI timeout doesn't fire first (#3304); pass\n // signal too for CLI-vs-API cancellation parity (#3036/#3304).\n timeoutMs,\n signal: AbortSignal.timeout(timeoutMs),\n };\n return withResponseFormat\n ? { ...base, responseFormat: { type: 'json_schema', schema: VOTE_JSON_SCHEMA } }\n : base;\n}\n\n/**\n * #3497: some backends don't silently ignore an unsupported `responseFormat`.\n * OpenRouter implements `json_schema` via provider tool-use, so a role routed to\n * a provider without tool-use returns a hard 404 \"No endpoints found that\n * support tool use\" instead of ignoring the field — silently shrinking the panel\n * (observed on devex/catfish). Detect it so the caller retries without it.\n */\nfunction isStructuredOutputUnsupported(errorMessage: string): boolean {\n return /support tool use/i.test(errorMessage);\n}\n\n/** One completion attempt: build → complete (timeout-bounded) → extract text. */\nasync function runVoteCompletion(\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n timeoutMs: number,\n withResponseFormat: boolean\n): Promise<{ ok: true; output: string } | { ok: false; error: string }> {\n const request = buildVoteRequest(role, proposal, timeoutMs, withResponseFormat);\n const timeoutResult = await withTimeout(\n adapter.complete(request),\n timeoutMs,\n `Vote timeout after ${String(timeoutMs)}ms for role: ${role}`\n );\n if (!timeoutResult.ok) return { ok: false, error: timeoutResult.error };\n const response = timeoutResult.value;\n if (!response.ok) return { ok: false, error: response.error.message };\n return { ok: true, output: extractTextFromResponse(response.value.content) };\n}\n\nexport async function executeSingleVoteAttempt(\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n timeoutMs: number\n): Promise<{ ok: true; vote: Vote; output: string } | { ok: false; error: string }> {\n let completion = await runVoteCompletion(role, proposal, adapter, timeoutMs, true);\n // #3497: retry once WITHOUT responseFormat when the backend rejects the\n // tool-use-backed structured-output ask, so the panel keeps full strength.\n if (!completion.ok && isStructuredOutputUnsupported(completion.error)) {\n completion = await runVoteCompletion(role, proposal, adapter, timeoutMs, false);\n }\n if (!completion.ok) return { ok: false, error: completion.error };\n\n try {\n // parseVoteResponse throws SyntheticVoteError if parsing fails — we only\n // accept real LLM votes, not synthetic fallbacks.\n const vote = parseVoteResponse(completion.output, role);\n return { ok: true, vote, output: completion.output };\n } catch (error) {\n if (error instanceof SyntheticVoteError) {\n return { ok: false, error: `Vote parsing failed: ${error.message}` };\n }\n throw error; // Re-throw unexpected errors\n }\n}\n\n/** Options for executeWithRetries. */\nexport interface RetryOptions {\n readonly role: VoterRole;\n readonly proposal: string;\n readonly adapter: IModelAdapter;\n readonly logger: ILogger;\n readonly timeoutMs: number;\n readonly maxRetries: number;\n}\n\n/**\n * Executes vote attempts with retry logic.\n * Returns the error message from last failed attempt, or undefined if successful.\n */\nexport async function executeWithRetries(\n opts: RetryOptions\n): Promise<{ vote: Vote; ok: true } | { error: string; ok: false }> {\n const { role, proposal, adapter, logger, timeoutMs, maxRetries } = opts;\n let lastError = '';\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n if (attempt > 0) {\n const isRateLimit = isRateLimitError(lastError);\n const baseDelay = isRateLimit ? RATE_LIMIT_RETRY_DELAY_MS : INITIAL_RETRY_DELAY_MS;\n const delayMs = baseDelay * Math.pow(2, attempt - 1);\n logger.debug('Retrying vote execution', { role, attempt, delayMs, isRateLimit });\n await delay(delayMs);\n }\n\n // #2472: per-attempt timing breakdown so investigators can see which\n // retry succeeded (or which attempt blew the cap). Total vote time\n // is already captured at the call-site; this fills the per-attempt gap.\n const attemptStart = Date.now();\n const result = await executeSingleVoteAttempt(role, proposal, adapter, timeoutMs);\n const attemptMs = Date.now() - attemptStart;\n if (result.ok) {\n logger.info('Vote attempt timing', {\n role,\n attempt: attempt + 1,\n attemptMs,\n succeeded: true,\n });\n return { vote: result.vote, ok: true };\n }\n\n lastError = result.error;\n const rateLimited = isRateLimitError(lastError);\n logger.info('Vote attempt timing', {\n role,\n attempt: attempt + 1,\n attemptMs,\n succeeded: false,\n rateLimited,\n });\n logger.warn('Vote attempt failed', {\n role,\n attempt: attempt + 1,\n maxRetries: maxRetries + 1,\n error: lastError,\n ...(rateLimited ? { rateLimited: true } : {}),\n });\n }\n\n return { error: lastError !== '' ? lastError : 'Unknown error after all retries', ok: false };\n}\n","/**\n * Overall-deadline racing for consensus voting (Issue #1871).\n *\n * Defensive layer above per-vote timeouts: even if a single\n * executeAgentVote() promise never settles (subprocess adapter hang,\n * IPC wait that swallows timeout, etc.), this helper guarantees the\n * whole consensus call returns bounded partial results.\n *\n * Each role's vote promise is raced against a shared wall-clock\n * deadline. Any role whose promise has not settled when the deadline\n * fires is filled with createErrorVoteResult('overall consensus\n * deadline exceeded'), preserving role order so downstream aggregation\n * stays deterministic.\n */\nimport type { IModelAdapter, ILogger } from '../core/index.js';\nimport type { AgentVoteResult, VoterRole } from './vote-types.js';\nimport { createErrorVoteResult, delay } from './voter-execution.js';\n\nexport interface VoteOptions {\n readonly timeoutMs: number;\n readonly maxRetries: number;\n readonly allowSimulation: boolean;\n}\n\nexport type VoteFn = (\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n logger: ILogger,\n options: VoteOptions\n) => Promise<AgentVoteResult>;\n\nexport interface LaunchVotesInput {\n readonly roles: readonly VoterRole[];\n readonly proposal: string;\n readonly roleAdapters: ReadonlyMap<VoterRole, IModelAdapter>;\n readonly fallbackAdapter: IModelAdapter;\n readonly logger: ILogger;\n readonly voteOptions: VoteOptions;\n readonly interDelay: number;\n readonly overallDeadlineMs: number;\n /** Vote launcher (injected by caller — typically executeAgentVote). */\n readonly voteFn: VoteFn;\n}\n\nconst DEADLINE_MESSAGE = 'overall consensus deadline exceeded';\n\n/**\n * Should a failed vote be retried on the fallback adapter? Only when the diverse\n * adapter produced a genuine error (not the overall-deadline filler, which means\n * there's no time left) AND it wasn't already the fallback (#3587).\n */\nfunction shouldRetryOnFallback(\n result: AgentVoteResult,\n used: IModelAdapter,\n fallback: IModelAdapter\n): boolean {\n return (\n result.source === 'error' &&\n result.error !== DEADLINE_MESSAGE &&\n adapterCliKey(used) !== adapterCliKey(fallback)\n );\n}\n\n/** Stable per-CLI key for an adapter; CLI adapters carry the CLI name. */\nfunction adapterCliKey(adapter: IModelAdapter): string {\n return (adapter as { name?: string }).name ?? adapter.providerId;\n}\n\n/**\n * Per-key serializer (#3348). Returns a `run(key, fn)` that chains each fn\n * behind the previous fn for the same key, so at most one runs per key at a\n * time. Different keys run concurrently.\n *\n * Why: when several voter roles round-robin onto the SAME CLI, concurrent\n * subprocesses each trigger that CLI's OAuth access-token refresh. With\n * refresh-token rotation the first call rotates the token and the rest fail\n * with \"refresh token already used\". Serializing per CLI lets the cold-start\n * refresh complete before the next same-CLI call begins. Cross-CLI parallelism\n * is preserved (claude/gemini/codex still overlap).\n */\nfunction createKeyedSerializer(): <T>(key: string, fn: () => Promise<T>) => Promise<T> {\n const tails = new Map<string, Promise<unknown>>();\n return <T>(key: string, fn: () => Promise<T>): Promise<T> => {\n const prev = tails.get(key) ?? Promise.resolve();\n // Run fn whether the previous same-key call resolved or rejected.\n const run = prev.then(fn, fn);\n // Chain on a never-rejecting tail so one failure can't break ordering.\n tails.set(\n key,\n run.then(\n () => undefined,\n () => undefined\n )\n );\n return run;\n };\n}\n\nfunction raceWithDeadline(\n p: Promise<AgentVoteResult>,\n role: VoterRole,\n deadlineMs: number\n): Promise<AgentVoteResult> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeoutP = new Promise<AgentVoteResult>((resolve) => {\n timer = setTimeout(() => {\n resolve(createErrorVoteResult(role, DEADLINE_MESSAGE, deadlineMs));\n }, deadlineMs);\n });\n return Promise.race([p, timeoutP]).finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n}\n\nexport async function launchVotesWithOverallDeadline(\n input: LaunchVotesInput\n): Promise<readonly AgentVoteResult[]> {\n const {\n roles,\n proposal,\n roleAdapters,\n fallbackAdapter,\n logger,\n voteOptions,\n interDelay,\n overallDeadlineMs,\n voteFn,\n } = input;\n\n const startedAt = Date.now();\n const serialize = createKeyedSerializer();\n\n // One serialized, deadline-bounded vote attempt on a specific adapter.\n const voteOnAdapter = (role: VoterRole, adapter: IModelAdapter): Promise<AgentVoteResult> =>\n // Serialize per CLI so concurrent same-CLI calls don't race that CLI's\n // OAuth refresh (#3348). The deadline is measured when the vote actually\n // starts, so a queued role still gets a correct remaining budget.\n serialize(adapterCliKey(adapter), () => {\n const remaining = Math.max(1, overallDeadlineMs - (Date.now() - startedAt));\n return raceWithDeadline(\n voteFn(role, proposal, adapter, logger, voteOptions),\n role,\n remaining\n );\n });\n\n const wrapped = roles.map(async (role, i): Promise<AgentVoteResult> => {\n if (i > 0 && interDelay > 0) await delay(interDelay);\n const adapter = roleAdapters.get(role) ?? fallbackAdapter;\n const primary = await voteOnAdapter(role, adapter);\n // #3587: a voter routed to a diverse CLI that hard-fails (e.g. an OpenRouter\n // model without tool-use → \"no endpoints that support tool use\", which the\n // responseFormat retry can't fix) would silently shrink the panel. Retry\n // once on the known-good fallback adapter so one bad CLI can't drop a voter.\n if (!shouldRetryOnFallback(primary, adapter, fallbackAdapter)) return primary;\n logger.warn('Voter failed on diverse adapter; retrying on fallback (#3587)', {\n role,\n failedCli: adapterCliKey(adapter),\n fallbackCli: adapterCliKey(fallbackAdapter),\n error: primary.error,\n });\n return voteOnAdapter(role, fallbackAdapter);\n });\n\n const results = await Promise.all(wrapped);\n\n const expired = results.filter((r) => r.source === 'error' && r.error === DEADLINE_MESSAGE);\n if (expired.length > 0) {\n logger.warn('Consensus overall deadline reached; returning partial results', {\n totalRoles: roles.length,\n expiredRoles: expired.map((r) => r.role),\n overallDeadlineMs,\n });\n }\n return results;\n}\n","/**\n * nexus-agents voter agents\n *\n * Real LLM-powered voter agents for consensus voting.\n * Replaces simulated voting with actual agent execution that\n * analyzes proposals.\n *\n * (Source: Issue #226, Sprint #229)\n * (Updated: Issue #280 - Fixed timeout handling, removed simulation fallback)\n * (Refactored: Issue #285 - Extracted response and execution utilities)\n *\n * File structure:\n * - voter-prompts.ts: System prompts for each voter role\n * - voter-response.ts: Response parsing and validation\n * - voter-execution.ts: Execution utilities (timeout, retry, result creation)\n * - voter-agents.ts: Main API (this file)\n */\n\nimport type { VoterRole, AgentVoteResult } from './vote-types.js';\nimport { VOTER_ROLES } from './vote-types.js';\nimport type { IModelAdapter, ILogger } from '../core/index.js';\nimport { createLogger, getTimeProvider, getErrorMessage } from '../core/index.js';\nimport { getGlobalRegistry } from '../adapters/unified-registry.js';\nimport { getAvailableClis } from '../cli-adapters/factory.js';\nimport { authRemediation } from '../cli-adapters/cli-error-envelope.js';\nimport type { CliName } from '../cli-adapters/types.js';\nimport { checkCodexConcurrency } from '../cli-adapters/codex-limits.js';\n\n// Re-export prompts for backward compatibility\nexport { VOTER_SYSTEM_PROMPTS, SIMULATED_VOTE_REASONING } from './voter-prompts.js';\n\n// Re-export response utilities for backward compatibility\nexport {\n VoteResponseSchema,\n type VoteResponse,\n buildVotePrompt,\n extractJsonFromResponse,\n parseVoteResponse,\n SyntheticVoteError,\n type ParsedVote,\n type ParsedVoteSource,\n type ParseVoteOptions,\n} from './voter-response.js';\n\n// Re-export execution utilities for backward compatibility\nexport {\n DEFAULT_VOTE_TIMEOUT_MS,\n MAX_VOTE_TIMEOUT_MS,\n MIN_VOTE_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n RATE_LIMIT_RETRY_DELAY_MS,\n createErrorVoteResult,\n createSimulationVoteResult,\n createSimulatedVotes,\n simulateVote,\n isRateLimitError,\n withTimeout,\n delay,\n extractTextFromResponse,\n executeSingleVoteAttempt,\n resolveVoteTimeout,\n type RetryOptions,\n executeWithRetries,\n} from './voter-execution.js';\n\n// Import from execution module for internal use\nimport {\n createErrorVoteResult,\n createSimulationVoteResult,\n createSimulatedVotes,\n executeWithRetries,\n} from './voter-execution.js';\nimport { resolveVoteTimeout, VOTE_TIMEOUTS, getMcpSafeDeadlineMs } from '../config/timeouts.js';\nimport { launchVotesWithOverallDeadline } from './voter-agents-deadline.js';\n\n/**\n * Computes an overall wall-clock deadline for a consensus vote call (#1871).\n *\n * Acts as a safety net above per-vote timeouts: even if executeAgentVote's\n * internal withTimeout race fails to resolve (e.g. subprocess adapter hang),\n * this deadline bounds total wall time and lets partial results return.\n *\n * Formula: worst-case legitimate completion (timeoutMs * (maxRetries+1))\n * plus staggered launch headroom, plus `VOTE_TIMEOUTS.overallDeadlineBufferMs`.\n */\nexport function computeOverallConsensusDeadlineMs(\n timeoutMs: number,\n maxRetries: number,\n roleCount: number,\n interDelayMs: number\n): number {\n const perVoteBudget = timeoutMs * (maxRetries + 1);\n const staggerBudget = Math.max(0, roleCount - 1) * interDelayMs;\n return perVoteBudget + staggerBudget + VOTE_TIMEOUTS.overallDeadlineBufferMs;\n}\n\n// ============================================================================\n// Agent Vote Execution\n// ============================================================================\n\n/**\n * Options for executing voter agents.\n */\n/** Default inter-agent delay to prevent rate limiting (ms). Raised from 1s to 2s (#1802). */\nexport const DEFAULT_INTER_AGENT_DELAY_MS = 2000;\n\nexport interface VoterAgentOptions {\n /** Logger instance */\n readonly logger?: ILogger;\n /** Model adapter to use (auto-selected if not provided) */\n readonly adapter?: IModelAdapter;\n /** Timeout per vote in milliseconds (default: 120000, override via NEXUS_VOTE_TIMEOUT_MS) */\n readonly timeoutMs?: number;\n /** Maximum retries per vote (default: 2) */\n readonly maxRetries?: number;\n /** Whether to allow simulation fallback (default: false per Issue #280) */\n readonly allowSimulation?: boolean;\n /** Delay between launching each agent vote to prevent rate limiting (default: 1000ms). Set to 0 to disable. */\n readonly interAgentDelayMs?: number;\n}\n\n// Re-export AgentVoteResult for convenience\nexport type { AgentVoteResult };\n\nconst defaultLogger = createLogger({ component: 'voter-agents' });\n\n/**\n * Executes a real LLM vote for a single role with timeout and retry support.\n *\n * Per Issue #280: No simulation fallback by default. Returns error result\n * instead of simulated vote when execution fails.\n */\nexport async function executeAgentVote(\n role: VoterRole,\n proposal: string,\n adapter: IModelAdapter,\n logger: ILogger,\n options?: { timeoutMs?: number; maxRetries?: number; allowSimulation?: boolean }\n): Promise<AgentVoteResult> {\n const start = getTimeProvider().now();\n const timeoutMs = options?.timeoutMs ?? resolveVoteTimeout();\n const maxRetries = options?.maxRetries ?? VOTE_TIMEOUTS.maxRetries;\n const allowSimulation = options?.allowSimulation ?? false;\n\n logger.info('Executing vote', { role, model: adapter.modelId, provider: adapter.providerId });\n\n const result = await executeWithRetries({\n role,\n proposal,\n adapter,\n logger,\n timeoutMs,\n maxRetries,\n });\n const processingTimeMs = getTimeProvider().now() - start;\n\n if (result.ok) {\n logger.info('Vote completed', { role, model: adapter.modelId, decision: result.vote.decision });\n return { role, vote: result.vote, processingTimeMs, source: 'llm', cli: adapter.providerId };\n }\n\n // All retries exhausted\n logger.error('Vote execution failed after all retries', undefined, {\n role,\n model: adapter.modelId,\n errorMessage: result.error,\n });\n\n if (allowSimulation) {\n logger.warn('Falling back to simulation (allowSimulation=true)', { role });\n return createSimulationVoteResult(role, proposal, processingTimeMs, result.error);\n }\n\n // #3350: a stale-OAuth failure (e.g. codex \"refresh token already used\")\n // surfaces here as a raw fail-closed error with no operator signal. Append a\n // one-line `<cli> login` remediation when the error is an auth error. Vote\n // semantics are unchanged — this is still an error (abstain) vote.\n const remediation = authRemediation(result.error, adapter.providerId);\n const errorText = remediation === null ? result.error : `${result.error}\\n\\n${remediation}`;\n return createErrorVoteResult(role, errorText, processingTimeMs);\n}\n\n// ============================================================================\n// Batch Vote Collection\n// ============================================================================\n\n/**\n * Options for collecting votes from multiple agents.\n */\nexport interface CollectRealVotesOptions extends VoterAgentOptions {\n /** Voter roles to include */\n readonly roles: readonly VoterRole[];\n /** Proposal text */\n readonly proposal: string;\n /** Use simulation mode (explicit opt-in only) */\n readonly simulate?: boolean;\n}\n\n/**\n * Error thrown when no adapter is available and simulation is disabled.\n */\nexport class NoAdapterError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NoAdapterError';\n }\n}\n\n/**\n * Resolves the model adapter, handling errors per Issue #280.\n */\nfunction resolveAdapter(\n options: CollectRealVotesOptions,\n logger: ILogger\n): { adapter: IModelAdapter } | { error: string } {\n try {\n if (options.adapter !== undefined) return { adapter: options.adapter };\n const registry = getGlobalRegistry({ logger });\n return { adapter: registry.getDefault() };\n } catch (error) {\n return { error: getErrorMessage(error) };\n }\n}\n\n/**\n * #2659 — warn (don't block) when more voter roles land on Codex than its\n * default `max_threads`, e.g. a single-CLI fallback with a full panel.\n */\nfunction warnIfCodexConcurrencyExceeded(\n roleAdapters: ReadonlyMap<VoterRole, IModelAdapter>,\n logger: ILogger\n): void {\n const codexBound = [...roleAdapters.values()].filter(\n (a) => (a as { name?: string }).name === 'codex'\n ).length;\n const warning = checkCodexConcurrency(codexBound);\n if (warning !== null) {\n logger.warn('Codex concurrency limit may be exceeded', { detail: warning });\n }\n}\n\n/** Assigns a single adapter to all roles (fallback path). */\nfunction assignUniformAdapter(\n roles: readonly VoterRole[],\n adapter: IModelAdapter\n): Map<VoterRole, IModelAdapter> {\n const adapters = new Map<VoterRole, IModelAdapter>();\n for (const role of roles) adapters.set(role, adapter);\n return adapters;\n}\n\n/** Creates CLI-specific adapters for available CLIs via the unified registry. */\nfunction createCliAdapterMap(\n clis: readonly CliName[],\n logger: ILogger\n): Map<CliName, IModelAdapter> {\n const registry = getGlobalRegistry({ logger });\n const result = new Map<CliName, IModelAdapter>();\n for (const cli of clis) {\n result.set(cli, registry.getAdapterForCli(cli));\n }\n return result;\n}\n\n/**\n * Creates diverse per-role adapters using all available CLIs (Issue #845).\n * Distributes roles across CLIs in round-robin fashion for model diversity.\n * Falls back to single adapter if only one CLI is available.\n */\nasync function resolveDiverseAdapters(\n roles: readonly VoterRole[],\n logger: ILogger,\n fallbackAdapter: IModelAdapter\n): Promise<Map<VoterRole, IModelAdapter>> {\n let availableClis: CliName[];\n try {\n availableClis = await getAvailableClis();\n } catch (e: unknown) {\n logger.warn('Failed to resolve available CLIs; falling back to single adapter', {\n error: String(e),\n });\n availableClis = [];\n }\n\n if (availableClis.length <= 1) {\n logger.info('Using single adapter for all roles', { cliCount: availableClis.length });\n return assignUniformAdapter(roles, fallbackAdapter);\n }\n\n const cliAdapters = createCliAdapterMap(availableClis, logger);\n if (cliAdapters.size <= 1) return assignUniformAdapter(roles, fallbackAdapter);\n\n // Round-robin assign roles to diverse CLIs\n const cliList = [...cliAdapters.entries()];\n const adapters = new Map<VoterRole, IModelAdapter>();\n const assignments: Record<string, string> = {};\n for (let i = 0; i < roles.length; i++) {\n const role = roles[i];\n const entry = cliList[i % cliList.length];\n if (role === undefined || entry === undefined) continue;\n adapters.set(role, entry[1]);\n assignments[role] = entry[0];\n }\n\n logger.info('Diverse adapters assigned', {\n cliCount: cliAdapters.size,\n clis: [...cliAdapters.keys()],\n roleAssignments: assignments,\n });\n return adapters;\n}\n\n/** Options for staggered vote launching. */\ninterface StaggeredVoteInput {\n readonly roles: readonly VoterRole[];\n readonly proposal: string;\n readonly roleAdapters: Map<VoterRole, IModelAdapter>;\n readonly fallbackAdapter: IModelAdapter;\n readonly logger: ILogger;\n readonly voteOptions: { timeoutMs: number; maxRetries: number; allowSimulation: boolean };\n readonly interDelay: number;\n}\n\n/**\n * Launches votes with staggered delays to prevent rate limiting (Issue #1319)\n * and an overall wall-clock deadline to prevent indefinite hangs (Issue #1871).\n */\nasync function launchStaggeredVotes(\n input: StaggeredVoteInput\n): Promise<readonly AgentVoteResult[]> {\n const { roles, proposal, roleAdapters, fallbackAdapter, logger, voteOptions, interDelay } = input;\n // Raw \"worst legitimate completion\" estimate — retained unchanged so the\n // formula still answers \"how long could this vote take in principle?\".\n const computedDeadlineMs = computeOverallConsensusDeadlineMs(\n voteOptions.timeoutMs,\n voteOptions.maxRetries,\n roles.length,\n interDelay\n );\n // Clamp below the outer MCP tool-wrapper timeout. Without this, the\n // middleware kills the promise chain before launchVotesWithOverallDeadline\n // can produce structured partial results — clients see a naked timeout\n // error instead of a `source: 'error' / error: 'overall consensus deadline\n // exceeded'` vote per stuck role. (Issue #2105)\n const overallDeadlineMs = getMcpSafeDeadlineMs(computedDeadlineMs, 'consensus_vote');\n if (overallDeadlineMs < computedDeadlineMs) {\n logger.debug('Consensus deadline clamped to MCP wrapper timeout', {\n computedDeadlineMs,\n overallDeadlineMs,\n });\n }\n return launchVotesWithOverallDeadline({\n roles,\n proposal,\n roleAdapters,\n fallbackAdapter,\n logger,\n voteOptions,\n interDelay,\n overallDeadlineMs,\n voteFn: executeAgentVote,\n });\n}\n\n/**\n * Collects votes from multiple voter agents.\n *\n * Per Issue #280: No automatic simulation fallback. If no adapter is\n * available and simulation is not explicitly enabled, throws NoAdapterError.\n * Per Issue #845: Uses diverse CLIs when multiple are available.\n */\nexport async function collectRealVotes(\n options: CollectRealVotesOptions\n): Promise<readonly AgentVoteResult[]> {\n const logger = options.logger ?? defaultLogger;\n const { roles, proposal, simulate, allowSimulation } = options;\n const timeoutMs = options.timeoutMs ?? resolveVoteTimeout();\n const maxRetries = options.maxRetries ?? VOTE_TIMEOUTS.maxRetries;\n\n if (simulate === true) {\n logger.info('Using simulation mode (explicitly requested)');\n return createSimulatedVotes(roles, proposal);\n }\n\n const adapterResult = resolveAdapter(options, logger);\n\n if ('error' in adapterResult) {\n logger.error('No adapter available for voting', undefined, { error: adapterResult.error });\n\n if (allowSimulation === true) {\n logger.warn('Falling back to simulation (allowSimulation=true)');\n return createSimulatedVotes(roles, proposal, 'No adapter available');\n }\n\n throw new NoAdapterError(\n `No adapter available for voting: ${adapterResult.error}. ` +\n 'Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY.'\n );\n }\n\n // Per Issue #845: Use diverse adapters when no explicit adapter is provided\n const roleAdapters =\n options.adapter !== undefined\n ? assignUniformAdapter(roles, adapterResult.adapter)\n : await resolveDiverseAdapters(roles, logger, adapterResult.adapter);\n\n warnIfCodexConcurrencyExceeded(roleAdapters, logger);\n\n const voteOptions = { timeoutMs, maxRetries, allowSimulation: allowSimulation ?? false };\n const interDelay = options.interAgentDelayMs ?? DEFAULT_INTER_AGENT_DELAY_MS;\n\n return launchStaggeredVotes({\n roles,\n proposal,\n roleAdapters,\n fallbackAdapter: adapterResult.adapter,\n logger,\n voteOptions,\n interDelay,\n });\n}\n\n/**\n * Gets a description for a voter role.\n */\nexport function getRoleDescription(role: VoterRole): string {\n return VOTER_ROLES[role];\n}\n","/**\n * nexus-agents/consensus - Multi-Round Voting Protocol Types\n *\n * Multi-Round Voting Protocol Types (Issue #100)\n * Based on arXiv:2512.21352 - Multi-Agent Committees for Code Review\n */\n\nimport { z } from 'zod';\nimport type { Vote } from './types-core.js';\nimport { SUPERMAJORITY_THRESHOLD } from './types-core.js';\nimport { OPERATION_CLASSES } from '../config/timeouts.js';\n\n/**\n * Default per-round voting timeout (#3734). A voting round guards a parallel\n * MULTI-LLM panel, so it derives from the central `multi-llm-panel` runaway-guard\n * (900s) — not the old accidental 60s, which killed legitimate slow voters.\n */\nconst VOTING_ROUND_DEFAULT_TIMEOUT_MS = OPERATION_CLASSES['multi-llm-panel'].guardMs;\n\n/**\n * Voting round phases.\n * - analysis: Independent analysis (Round 1)\n * - deliberation: Share findings and discuss (Round 2)\n * - consensus: Final vote on recommendations (Round 3)\n */\nexport const VotingRoundPhaseSchema = z.enum(['analysis', 'deliberation', 'consensus']);\nexport type VotingRoundPhase = z.infer<typeof VotingRoundPhaseSchema>;\n\n/**\n * Voting round status.\n */\nexport const VotingRoundStatusSchema = z.enum([\n 'pending',\n 'in_progress',\n 'awaiting_votes',\n 'completed',\n 'aborted',\n]);\nexport type VotingRoundStatus = z.infer<typeof VotingRoundStatusSchema>;\n\n/**\n * A finding submitted by an agent during analysis.\n */\nexport const AgentFindingSchema = z.object({\n agentId: z.string(),\n category: z.enum(['bug', 'security', 'performance', 'style', 'design', 'documentation', 'other']),\n severity: z.enum(['critical', 'major', 'minor', 'suggestion']),\n description: z.string().min(1),\n location: z.string().optional().describe('File path and line range if applicable'),\n suggestion: z.string().optional().describe('Recommended fix'),\n confidence: z.number().min(0).max(1),\n timestamp: z.iso.datetime().optional(),\n});\nexport type AgentFinding = z.infer<typeof AgentFindingSchema>;\n\n/**\n * Finding vote during deliberation.\n */\nexport const FindingVoteSchema = z.object({\n agentId: z.string(),\n findingId: z.string(),\n agree: z.boolean(),\n reasoning: z.string().optional(),\n amendedSeverity: z.enum(['critical', 'major', 'minor', 'suggestion']).optional(),\n});\nexport type FindingVote = z.infer<typeof FindingVoteSchema>;\n\n/**\n * A single voting round in the protocol.\n */\nexport interface VotingRound {\n id: string;\n phase: VotingRoundPhase;\n status: VotingRoundStatus;\n findings: Map<string, AgentFinding>; // findingId -> finding\n findingVotes: Map<string, FindingVote[]>; // findingId -> votes\n finalVotes: Map<string, Vote>; // agentId -> final vote\n startedAt: string;\n completedAt?: string;\n roundNumber: number;\n}\n\n/**\n * Configuration for the voting protocol.\n */\nexport interface VotingProtocolConfig {\n /** Number of agents in the committee (default: 3) */\n committeeSize: number;\n /** Maximum rounds before forcing decision (default: 3) */\n maxRounds: number;\n /** Timeout per round in milliseconds (default: multi-llm-panel guard, 900000) */\n roundTimeoutMs: number;\n /** Minimum agreement threshold (default: 0.67) */\n agreementThreshold: number;\n /** Enable anti-sycophancy detection (default: true) */\n enableAntiSycophancy: boolean;\n /** Similarity threshold for sycophancy detection (default: 0.8) */\n sycophancyThreshold: number;\n}\n\nexport const VotingProtocolConfigSchema = z.object({\n committeeSize: z.number().int().min(2).max(7).default(3),\n maxRounds: z.number().int().min(1).max(5).default(3),\n roundTimeoutMs: z.number().int().positive().default(VOTING_ROUND_DEFAULT_TIMEOUT_MS),\n agreementThreshold: z.number().min(0.5).max(1).default(SUPERMAJORITY_THRESHOLD),\n enableAntiSycophancy: z.boolean().default(true),\n sycophancyThreshold: z.number().min(0).max(1).default(0.8),\n});\n\nexport const DEFAULT_VOTING_PROTOCOL_CONFIG: VotingProtocolConfig = {\n committeeSize: 3,\n maxRounds: 3,\n roundTimeoutMs: VOTING_ROUND_DEFAULT_TIMEOUT_MS,\n // Default agreement level IS the supermajority (2/3) — single source (#3571).\n agreementThreshold: SUPERMAJORITY_THRESHOLD,\n enableAntiSycophancy: true,\n sycophancyThreshold: 0.8,\n};\n\n/**\n * Session state for a voting protocol instance.\n */\nexport interface VotingSession {\n id: string;\n topic: string;\n committee: string[]; // Agent IDs\n rounds: VotingRound[];\n currentRound: number;\n config: VotingProtocolConfig;\n status: 'active' | 'completed' | 'aborted';\n createdAt: string;\n completedAt?: string;\n finalResult?: VotingProtocolResult;\n}\n\n/**\n * Final result of a voting protocol session.\n */\nexport interface VotingProtocolResult {\n sessionId: string;\n topic: string;\n outcome: 'approved' | 'rejected' | 'needs_revision' | 'no_consensus';\n consolidatedFindings: ConsolidatedFinding[];\n roundSummaries: RoundSummary[];\n agreementScore: number;\n sycophancyDetected: boolean;\n totalDurationMs: number;\n participatingAgents: string[];\n}\n\n/**\n * A consolidated finding after deliberation.\n */\nexport interface ConsolidatedFinding {\n id: string;\n category: AgentFinding['category'];\n severity: AgentFinding['severity'];\n description: string;\n location?: string;\n suggestion?: string;\n supportingAgents: string[];\n agreementRatio: number;\n originalFindings: AgentFinding[];\n}\n\n/**\n * Summary of a single round.\n */\nexport interface RoundSummary {\n roundNumber: number;\n phase: VotingRoundPhase;\n findingsCount: number;\n votesCount: number;\n agreementScore: number;\n durationMs: number;\n}\n\n/**\n * Interface for the multi-round voting protocol.\n * (Source: Issue #100, arXiv:2512.21352)\n */\nexport interface IVotingProtocol {\n /** Create a new voting session with a committee */\n createSession(\n topic: string,\n committee: string[],\n config?: Partial<VotingProtocolConfig>\n ): VotingSession;\n\n /** Start the analysis round (Round 1) */\n startAnalysisRound(sessionId: string): Promise<VotingRound>;\n\n /** Submit findings from an agent during analysis */\n submitFindings(sessionId: string, agentId: string, findings: AgentFinding[]): Promise<void>;\n\n /** Start the deliberation round (Round 2) */\n startDeliberationRound(sessionId: string): Promise<VotingRound>;\n\n /** Vote on findings during deliberation */\n voteOnFinding(sessionId: string, vote: FindingVote): Promise<void>;\n\n /** Start the consensus round (Round 3) */\n startConsensusRound(sessionId: string): Promise<VotingRound>;\n\n /** Submit final vote during consensus */\n submitFinalVote(sessionId: string, agentId: string, vote: Vote): Promise<void>;\n\n /** Get the final result (closes session if complete) */\n getResult(sessionId: string): Promise<VotingProtocolResult | null>;\n\n /** Check for sycophancy in the current round */\n detectSycophancy(sessionId: string): SycophancyReport;\n\n /** Get the current session state */\n getSession(sessionId: string): VotingSession | undefined;\n}\n\n/**\n * Report from sycophancy detection.\n */\nexport interface SycophancyReport {\n detected: boolean;\n confidenceScore: number;\n indicators: SycophancyIndicator[];\n affectedAgents: string[];\n recommendation: string;\n}\n\n/**\n * Individual sycophancy indicator.\n */\nexport interface SycophancyIndicator {\n type: 'premature_consensus' | 'opinion_convergence' | 'confidence_inflation' | 'echo_chamber';\n description: string;\n severity: 'low' | 'medium' | 'high';\n agents: string[];\n}\n","/**\n * nexus-agents/consensus - Weighted Byzantine Voting Types\n *\n * Weighted Byzantine Voting Types (Issue #103)\n * Based on CP-WBFT (arXiv:2511.10400)\n */\n\nimport { z } from 'zod';\nimport type { Vote } from './types-core.js';\nimport { SUPERMAJORITY_THRESHOLD } from './types-core.js';\n\n/**\n * Task outcome STATUS for tracking agent performance — a 4-state vote status,\n * NOT an outcome row. Named `*Status` to avoid colliding with the canonical\n * outcome *record* `TaskOutcome` in orchestration/outcomes (#3146/#3226: the\n * two were unrelated types that happened to share the name `TaskOutcome`).\n */\nexport const TaskOutcomeStatusSchema = z.enum(['success', 'failure', 'partial', 'unknown']);\nexport type TaskOutcomeStatus = z.infer<typeof TaskOutcomeStatusSchema>;\n\n/**\n * Extended agent performance with Byzantine detection.\n */\nexport interface WeightedAgentRecord {\n readonly agentId: string;\n readonly totalTasks: number;\n readonly successfulTasks: number;\n readonly failedTasks: number;\n readonly partialTasks: number;\n readonly successRate: number;\n readonly weight: number;\n readonly trustScore: number;\n readonly byzantineFlags: number;\n readonly lastActive: Date;\n readonly createdAt: Date;\n}\n\nexport const WeightedAgentRecordSchema = z.object({\n agentId: z.string().min(1),\n totalTasks: z.number().int().nonnegative(),\n successfulTasks: z.number().int().nonnegative(),\n failedTasks: z.number().int().nonnegative(),\n partialTasks: z.number().int().nonnegative(),\n successRate: z.number().min(0).max(1),\n weight: z.number().min(0).max(1),\n trustScore: z.number().min(0).max(1),\n byzantineFlags: z.number().int().nonnegative(),\n lastActive: z.date(),\n createdAt: z.date(),\n});\n\n/**\n * Weighted consensus result.\n */\nexport interface WeightedConsensusResult {\n readonly decision: 'approve' | 'reject' | 'no_consensus';\n readonly weightedApproval: number;\n readonly weightedRejection: number;\n readonly totalWeight: number;\n readonly quorumReached: boolean;\n readonly byzantineDetected: boolean;\n readonly participatingAgents: readonly string[];\n readonly weightBreakdown: ReadonlyMap<string, number>;\n}\n\n/**\n * Configuration for weighted Byzantine voting.\n */\nexport interface WeightedVotingConfig {\n /** Minimum weight to participate in voting (default: 0.1) */\n readonly minWeight: number;\n /** Maximum Byzantine fault tolerance (default: 0.33) */\n readonly maxByzantineFraction: number;\n /** Weight decay factor per failed task (default: 0.9) */\n readonly weightDecayFactor: number;\n /** Weight recovery factor per successful task (default: 1.05) */\n readonly weightRecoveryFactor: number;\n /** Trust score required to vote (default: 0.3) */\n readonly minTrustScore: number;\n /** Byzantine flag threshold for exclusion (default: 3) */\n readonly byzantineFlagThreshold: number;\n /** Initial weight for new agents (default: 0.5) */\n readonly initialWeight: number;\n /** Quorum threshold for valid consensus (default: 0.67) */\n readonly quorumThreshold: number;\n}\n\nexport const WeightedVotingConfigSchema = z.object({\n minWeight: z.number().min(0).max(1).default(0.1),\n maxByzantineFraction: z.number().min(0).max(0.5).default(0.33),\n weightDecayFactor: z.number().min(0.5).max(1).default(0.9),\n weightRecoveryFactor: z.number().min(1).max(2).default(1.05),\n minTrustScore: z.number().min(0).max(1).default(0.3),\n byzantineFlagThreshold: z.number().int().positive().default(3),\n initialWeight: z.number().min(0).max(1).default(0.5),\n quorumThreshold: z.number().min(0.5).max(1).default(SUPERMAJORITY_THRESHOLD),\n});\n\nexport const DEFAULT_WEIGHTED_VOTING_CONFIG: WeightedVotingConfig = {\n minWeight: 0.1,\n maxByzantineFraction: 0.33,\n weightDecayFactor: 0.9,\n weightRecoveryFactor: 1.05,\n minTrustScore: 0.3,\n byzantineFlagThreshold: 3,\n initialWeight: 0.5,\n // Default quorum IS the supermajority (2/3) — single source (#3571).\n quorumThreshold: SUPERMAJORITY_THRESHOLD,\n};\n\n/**\n * Interface for weighted Byzantine voting.\n * (Source: Issue #103, arXiv:2511.10400 - CP-WBFT)\n */\nexport interface IWeightedVoting {\n /** Calculate vote weight for an agent */\n calculateWeight(agentId: string): number;\n\n /** Update agent performance based on task outcome */\n updatePerformance(agentId: string, outcome: TaskOutcomeStatus): void;\n\n /** Run weighted consensus on votes */\n weightedConsensus(votes: ReadonlyMap<string, Vote>): WeightedConsensusResult;\n\n /** Register a new agent */\n registerAgent(agentId: string): void;\n\n /** Get agent performance record */\n getAgentRecord(agentId: string): WeightedAgentRecord | undefined;\n\n /** Flag agent for Byzantine behavior */\n flagByzantine(agentId: string, reason: string): void;\n\n /** Get all agent records */\n getAllRecords(): readonly WeightedAgentRecord[];\n\n /** Check if agent can vote */\n canVote(agentId: string): boolean;\n\n /** Recalibrate all weights based on global performance */\n recalibrateWeights(): void;\n}\n","/**\n * nexus-agents/consensus - Higher-Order Voting Types\n *\n * Type definitions for Opinion-Wise (OW) and Independent Subset Partition (ISP)\n * voting methods that account for correlations between agent opinions.\n *\n * Higher-order voting uses Bayesian-optimal aggregation that handles correlated\n * agents better than traditional independent voting assumptions.\n *\n * @module consensus/higher-order-types\n * (Source: Issue #333)\n */\n\nimport { z } from 'zod';\nimport type { Vote, VoteDecision } from './types-core.js';\n\n// ============================================================================\n// CORRELATION TYPES\n// ============================================================================\n\n/**\n * Pair of agent IDs for correlation tracking.\n * Stored as \"agentA:agentB\" where agentA < agentB lexicographically.\n */\nexport type AgentPairKey = `${string}:${string}`;\n\n/**\n * Creates a canonical agent pair key for correlation lookup.\n * Orders agents lexicographically to ensure consistent keys.\n */\nexport function createAgentPairKey(agentA: string, agentB: string): AgentPairKey {\n return agentA < agentB ? `${agentA}:${agentB}` : `${agentB}:${agentA}`;\n}\n\n/**\n * Extracts agent IDs from a pair key.\n */\nexport function parseAgentPairKey(key: AgentPairKey): [string, string] {\n const parts = key.split(':');\n if (parts.length !== 2 || parts[0] === undefined || parts[1] === undefined) {\n throw new Error(`Invalid agent pair key: ${key}`);\n }\n return [parts[0], parts[1]];\n}\n\n/**\n * Correlation coefficient between two agents' voting patterns.\n * Range: -1 (perfectly anti-correlated) to +1 (perfectly correlated).\n * 0 indicates independence.\n */\nexport const CorrelationCoefficientSchema = z.number().min(-1).max(1);\nexport type CorrelationCoefficient = z.infer<typeof CorrelationCoefficientSchema>;\n\n/**\n * Correlation matrix storing pairwise correlations between agents.\n */\nexport type CorrelationMatrix = Map<AgentPairKey, CorrelationCoefficient>;\n\n/**\n * A subset of agents that vote independently of each other.\n * Used in ISP (Independent Subset Partition) method.\n */\nexport interface IndependentSubset {\n /** Unique identifier for this subset */\n readonly id: string;\n /** Agent IDs in this independent subset */\n readonly agentIds: readonly string[];\n /** Average internal independence score (lower = more independent) */\n readonly independenceScore: number;\n /** Number of observations supporting this grouping */\n readonly observationCount: number;\n}\n\nexport const IndependentSubsetSchema = z.object({\n id: z.string(),\n agentIds: z.array(z.string()),\n independenceScore: z.number().min(0).max(1),\n observationCount: z.number().int().nonnegative(),\n});\n\n// ============================================================================\n// VOTING HISTORY TYPES\n// ============================================================================\n\n/**\n * Record of a single voting observation for correlation tracking.\n */\nexport interface VotingObservation {\n /** Unique proposal ID */\n readonly proposalId: string;\n /** Agent who cast the vote */\n readonly agentId: string;\n /** The vote decision */\n readonly decision: VoteDecision;\n /** Confidence level (0-1) */\n readonly confidence: number;\n /** Whether the vote aligned with the final outcome */\n readonly alignedWithOutcome: boolean;\n /** Timestamp of the vote */\n readonly timestamp: Date;\n}\n\nexport const VotingObservationSchema = z.object({\n proposalId: z.string(),\n agentId: z.string(),\n decision: z.enum(['approve', 'reject', 'abstain']),\n confidence: z.number().min(0).max(1),\n alignedWithOutcome: z.boolean(),\n timestamp: z.date(),\n});\n\n/**\n * Aggregated voting history for a pair of agents.\n */\nexport interface PairwiseVotingHistory {\n /** Agent pair key */\n readonly pairKey: AgentPairKey;\n /** Number of proposals where both agents voted */\n readonly jointObservations: number;\n /** Number of times both agents agreed */\n readonly agreements: number;\n /** Number of times agents disagreed */\n readonly disagreements: number;\n /** Computed correlation coefficient */\n readonly correlation: CorrelationCoefficient;\n /** Last update timestamp */\n readonly lastUpdated: Date;\n}\n\nexport const PairwiseVotingHistorySchema = z.object({\n pairKey: z.string() as z.ZodType<AgentPairKey>,\n jointObservations: z.number().int().nonnegative(),\n agreements: z.number().int().nonnegative(),\n disagreements: z.number().int().nonnegative(),\n correlation: CorrelationCoefficientSchema,\n lastUpdated: z.date(),\n});\n\n// ============================================================================\n// HIGHER-ORDER VOTING CONFIG\n// ============================================================================\n\n/**\n * Configuration for higher-order voting.\n */\nexport interface HigherOrderVotingConfig {\n /** Minimum observations before using correlation data (default: 10) */\n readonly minObservationsForCorrelation: number;\n /** Correlation threshold to consider agents correlated (default: 0.3) */\n readonly correlationThreshold: number;\n /** Maximum correlation age in milliseconds before recalculation (default: 24h) */\n readonly correlationMaxAgeMs: number;\n /** Independence threshold for ISP grouping (default: 0.2) */\n readonly independenceThreshold: number;\n /** Whether to fall back to simple voting when correlation data insufficient */\n readonly fallbackToSimpleVoting: boolean;\n /** Decay factor for old observations (0-1, default: 0.95) */\n readonly observationDecayFactor: number;\n /** Maximum observations to store per agent before FIFO eviction (default: 1000) */\n readonly maxObservationsPerAgent: number;\n /** Maximum total proposals to track before evicting oldest (default: 5000) */\n readonly maxProposals: number;\n /** Maximum pairwise history entries before LRU eviction (default: 100) */\n readonly maxTrackedPairs: number;\n}\n\nexport const HigherOrderVotingConfigSchema = z.object({\n minObservationsForCorrelation: z.number().int().positive().default(10),\n correlationThreshold: z.number().min(0).max(1).default(0.3),\n correlationMaxAgeMs: z.number().int().positive().default(86400000), // 24 hours\n independenceThreshold: z.number().min(0).max(1).default(0.2),\n fallbackToSimpleVoting: z.boolean().default(true),\n observationDecayFactor: z.number().min(0).max(1).default(0.95),\n maxObservationsPerAgent: z.number().int().positive().default(1000),\n maxProposals: z.number().int().positive().default(5000),\n maxTrackedPairs: z.number().int().positive().default(100),\n});\n\nexport const DEFAULT_HIGHER_ORDER_CONFIG: HigherOrderVotingConfig = {\n minObservationsForCorrelation: 10,\n correlationThreshold: 0.3,\n correlationMaxAgeMs: 86400000, // 24 hours\n independenceThreshold: 0.2,\n fallbackToSimpleVoting: true,\n observationDecayFactor: 0.95,\n maxObservationsPerAgent: 1000,\n maxProposals: 5000,\n maxTrackedPairs: 100,\n};\n\n// ============================================================================\n// HIGHER-ORDER VOTING RESULTS\n// ============================================================================\n\n/**\n * Result of Bayesian aggregation with correlation awareness.\n */\nexport interface HigherOrderVotingResult {\n /** Final decision */\n readonly decision: 'approve' | 'reject' | 'no_consensus';\n /** Posterior probability of approval */\n readonly posteriorApproval: number;\n /** Posterior probability of rejection */\n readonly posteriorRejection: number;\n /** Effective number of independent votes */\n readonly effectiveVoteCount: number;\n /** Whether correlation data was sufficient */\n readonly usedCorrelationData: boolean;\n /** Method used: 'ow' (opinion-wise), 'isp', or 'simple' (fallback) */\n readonly method: 'ow' | 'isp' | 'simple';\n /** Improvement over baseline majority voting (percentage points) */\n readonly improvementOverBaseline: number;\n /** Independent subsets used (if ISP method) */\n readonly independentSubsets?: readonly IndependentSubset[];\n /** Agents whose votes were down-weighted due to correlation */\n readonly downweightedAgents: readonly string[];\n /** Reasoning for the decision */\n readonly reasoning: string;\n}\n\nexport const HigherOrderVotingResultSchema = z.object({\n decision: z.enum(['approve', 'reject', 'no_consensus']),\n posteriorApproval: z.number().min(0).max(1),\n posteriorRejection: z.number().min(0).max(1),\n effectiveVoteCount: z.number().nonnegative(),\n usedCorrelationData: z.boolean(),\n method: z.enum(['ow', 'isp', 'simple']),\n improvementOverBaseline: z.number(),\n independentSubsets: z.array(IndependentSubsetSchema).optional(),\n downweightedAgents: z.array(z.string()),\n reasoning: z.string(),\n});\n\n// ============================================================================\n// CORRELATION TRACKER INTERFACE\n// ============================================================================\n\n/**\n * Statistics about correlation tracking.\n */\nexport interface CorrelationTrackerStats {\n /** Total agents being tracked */\n readonly totalAgents: number;\n /** Total agent pairs with correlation data */\n readonly trackedPairs: number;\n /** Total voting observations recorded */\n readonly totalObservations: number;\n /** Average correlation across all pairs */\n readonly averageCorrelation: number;\n /** Number of identified independent subsets */\n readonly independentSubsetCount: number;\n /** Pairs with sufficient data for correlation calculation */\n readonly pairsWithSufficientData: number;\n}\n\nexport const CorrelationTrackerStatsSchema = z.object({\n totalAgents: z.number().int().nonnegative(),\n trackedPairs: z.number().int().nonnegative(),\n totalObservations: z.number().int().nonnegative(),\n averageCorrelation: z.number(),\n independentSubsetCount: z.number().int().nonnegative(),\n pairsWithSufficientData: z.number().int().nonnegative(),\n});\n\n/**\n * Interface for correlation tracking between agents.\n */\nexport interface ICorrelationTracker {\n /**\n * Record a vote and its outcome for correlation tracking.\n */\n recordVote(agentId: string, vote: Vote, outcome: 'approved' | 'rejected'): void;\n\n /**\n * Record votes from multiple agents for the same proposal.\n */\n recordProposalVotes(\n proposalId: string,\n votes: ReadonlyMap<string, Vote>,\n outcome: 'approved' | 'rejected'\n ): void;\n\n /**\n * Compute the full correlation matrix for all tracked agents.\n */\n computeCorrelationMatrix(): CorrelationMatrix;\n\n /**\n * Get correlation between two specific agents.\n * Returns undefined if insufficient data.\n */\n getCorrelation(agentA: string, agentB: string): CorrelationCoefficient | undefined;\n\n /**\n * Identify groups of agents that vote independently.\n */\n identifyIndependentSubsets(): readonly IndependentSubset[];\n\n /**\n * Check if there is sufficient correlation data for a set of agents.\n */\n hasSufficientData(agentIds: readonly string[]): boolean;\n\n /**\n * Get statistics about the correlation tracker.\n */\n getStats(): CorrelationTrackerStats;\n\n /**\n * Clear all recorded data.\n */\n clear(): void;\n}\n\n// ============================================================================\n// OW VOTING INTERFACE\n// ============================================================================\n\n/**\n * Interface for Opinion-Wise higher-order voting.\n */\nexport interface IHigherOrderVoting {\n /**\n * Aggregate votes using Bayesian correlation-aware method.\n */\n aggregateWithCorrelation(\n votes: ReadonlyMap<string, Vote>,\n correlationMatrix: CorrelationMatrix\n ): HigherOrderVotingResult;\n\n /**\n * Estimate correlation matrix from voting history.\n */\n estimateCorrelation(tracker: ICorrelationTracker): CorrelationMatrix;\n\n /**\n * Compute result using Independent Subset Partition method.\n */\n computeISP(\n votes: ReadonlyMap<string, Vote>,\n independentSubsets: readonly IndependentSubset[]\n ): HigherOrderVotingResult;\n\n /**\n * Full pipeline: estimate correlation, compute result.\n */\n aggregate(\n votes: ReadonlyMap<string, Vote>,\n tracker: ICorrelationTracker\n ): HigherOrderVotingResult;\n\n /**\n * Get the current configuration.\n */\n getConfig(): HigherOrderVotingConfig;\n}\n","/**\n * nexus-agents/consensus - Higher-Order Voting Helpers\n *\n * Helper functions for Opinion-Wise (OW) and Independent Subset Partition (ISP)\n * voting methods. Extracted from higher-order-voting.ts to maintain file size limits.\n *\n * @module consensus/higher-order-helpers\n * (Source: Issue #333, #339)\n */\n\nimport type { Vote } from './types-core.js';\nimport type {\n CorrelationMatrix,\n HigherOrderVotingResult,\n IndependentSubset,\n} from './higher-order-types.js';\nimport { createAgentPairKey } from './higher-order-types.js';\n\n/**\n * Result of Bayesian aggregation.\n */\nexport interface BayesianAggregateResult {\n readonly posteriorApproval: number;\n readonly posteriorRejection: number;\n readonly effectiveVoteCount: number;\n readonly downweightedAgents: string[];\n}\n\n/**\n * Result of subset aggregation.\n */\nexport interface SubsetAggregationResult {\n readonly subsetResults: Array<{ approval: number; rejection: number; weight: number }>;\n readonly downweightedAgents: string[];\n}\n\n/**\n * Result of combined subset results.\n */\nexport interface CombinedSubsetResult {\n readonly posteriorApproval: number;\n readonly posteriorRejection: number;\n readonly totalWeight: number;\n}\n\n/**\n * Check if there is sufficient correlation data for analysis.\n */\nexport function hasSufficientCorrelationData(\n agentIds: readonly string[],\n correlationMatrix: CorrelationMatrix\n): boolean {\n if (agentIds.length < 2) return false;\n\n let pairsWithData = 0;\n const totalPairs = (agentIds.length * (agentIds.length - 1)) / 2;\n\n for (let i = 0; i < agentIds.length; i++) {\n for (let j = i + 1; j < agentIds.length; j++) {\n const agentA = agentIds[i];\n const agentB = agentIds[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n if (correlationMatrix.has(pairKey)) {\n pairsWithData++;\n }\n }\n }\n }\n\n return pairsWithData >= Math.ceil(totalPairs * 0.5);\n}\n\n/**\n * Compute effective weights for agents based on correlations.\n * Reduces weights for highly correlated agents.\n */\nexport function computeEffectiveWeights(\n agentIds: readonly string[],\n correlationMatrix: CorrelationMatrix,\n correlationThreshold: number\n): Map<string, number> {\n const weights = new Map<string, number>();\n\n // Start with equal weights\n for (const agentId of agentIds) {\n weights.set(agentId, 1.0);\n }\n\n // Reduce weights for highly correlated agents\n for (let i = 0; i < agentIds.length; i++) {\n for (let j = i + 1; j < agentIds.length; j++) {\n const agentA = agentIds[i];\n const agentB = agentIds[j];\n if (agentA === undefined || agentB === undefined) continue;\n\n const pairKey = createAgentPairKey(agentA, agentB);\n const correlation = correlationMatrix.get(pairKey);\n\n if (correlation !== undefined && correlation > correlationThreshold) {\n // Reduce weight proportionally to correlation\n const reduction = correlation * 0.5;\n const currentWeightA = weights.get(agentA) ?? 1.0;\n const currentWeightB = weights.get(agentB) ?? 1.0;\n\n // Apply reduction to both agents (but less to avoid over-penalizing)\n weights.set(agentA, Math.max(0.1, currentWeightA - reduction * 0.5));\n weights.set(agentB, Math.max(0.1, currentWeightB - reduction * 0.5));\n }\n }\n }\n\n // NOTE (#3172, investigated + rejected): a \"restore uniform weights when all\n // collapse to the floor\" guard was considered but is incorrect. When agents\n // are equally correlated, equal downweighting is the CORRECT behavior (they\n // are equally redundant), and because the Bayesian aggregate is a weighted\n // average, scaling all weights equally is invariant — all-at-floor yields the\n // same posterior as uniform, so it is not degenerate. Restoring uniform would\n // wrongly treat correlated agents as independent and inflate the effective\n // vote count (guarded by the \"all perfectly correlated\" test).\n\n return weights;\n}\n\n/**\n * Perform Bayesian aggregation of votes with effective weights.\n */\nexport function bayesianAggregate(\n votes: ReadonlyMap<string, Vote>,\n effectiveWeights: Map<string, number>\n): BayesianAggregateResult {\n let weightedApproval = 0;\n let weightedRejection = 0;\n let totalWeight = 0;\n const downweightedAgents: string[] = [];\n\n for (const [agentId, vote] of votes) {\n const weight = effectiveWeights.get(agentId) ?? 1.0;\n\n // Track downweighted agents\n if (weight < 0.8) {\n downweightedAgents.push(agentId);\n }\n\n // Weight by confidence and effective weight\n const effectiveWeight = weight * vote.confidence;\n totalWeight += effectiveWeight;\n\n if (vote.decision === 'approve') {\n weightedApproval += effectiveWeight;\n } else if (vote.decision === 'reject') {\n weightedRejection += effectiveWeight;\n }\n // Abstains contribute to total weight but not to either side\n }\n\n const posteriorApproval = totalWeight > 0 ? weightedApproval / totalWeight : 0.5;\n const posteriorRejection = totalWeight > 0 ? weightedRejection / totalWeight : 0.5;\n const effectiveVoteCount = totalWeight;\n\n return { posteriorApproval, posteriorRejection, effectiveVoteCount, downweightedAgents };\n}\n\n/**\n * Aggregate votes within independent subsets.\n */\nexport function aggregateSubsets(\n votes: ReadonlyMap<string, Vote>,\n independentSubsets: readonly IndependentSubset[]\n): SubsetAggregationResult {\n const subsetResults: Array<{ approval: number; rejection: number; weight: number }> = [];\n const downweightedAgents: string[] = [];\n\n for (const subset of independentSubsets) {\n const subsetVotes = new Map<string, Vote>();\n for (const agentId of subset.agentIds) {\n const vote = votes.get(agentId);\n if (vote !== undefined) subsetVotes.set(agentId, vote);\n }\n if (subsetVotes.size === 0) continue;\n\n const { approval, rejection } = countSubsetVotes(subsetVotes);\n const weight = subsetVotes.size * (1 - subset.independenceScore);\n subsetResults.push({ approval, rejection, weight });\n\n if (subset.agentIds.length === 1) downweightedAgents.push(...subset.agentIds);\n }\n return { subsetResults, downweightedAgents };\n}\n\n/**\n * Combine subset results into overall posterior probabilities.\n */\nexport function combineSubsetResults(\n subsetResults: readonly { approval: number; rejection: number; weight: number }[]\n): CombinedSubsetResult {\n let totalApproval = 0;\n let totalRejection = 0;\n let totalWeight = 0;\n for (const { approval, rejection, weight } of subsetResults) {\n totalApproval += approval * weight;\n totalRejection += rejection * weight;\n totalWeight += weight;\n }\n return {\n posteriorApproval: totalWeight > 0 ? totalApproval / totalWeight : 0.5,\n posteriorRejection: totalWeight > 0 ? totalRejection / totalWeight : 0.5,\n totalWeight,\n };\n}\n\n/**\n * Count votes within a subset, weighted by confidence.\n */\nexport function countSubsetVotes(votes: ReadonlyMap<string, Vote>): {\n approval: number;\n rejection: number;\n} {\n let approval = 0;\n let rejection = 0;\n\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') {\n approval += vote.confidence;\n } else if (vote.decision === 'reject') {\n rejection += vote.confidence;\n }\n }\n\n const total = approval + rejection;\n return {\n approval: total > 0 ? approval / total : 0.5,\n rejection: total > 0 ? rejection / total : 0.5,\n };\n}\n\n/**\n * Determine decision based on posterior probabilities.\n */\nexport function determineHigherOrderDecision(\n posteriorApproval: number,\n posteriorRejection: number\n): 'approve' | 'reject' | 'no_consensus' {\n const diff = Math.abs(posteriorApproval - posteriorRejection);\n\n // Require significant margin for decision\n if (diff < 0.1) {\n return 'no_consensus';\n }\n\n return posteriorApproval > posteriorRejection ? 'approve' : 'reject';\n}\n\n/**\n * Perform simple majority aggregation (no correlation data).\n */\nexport function aggregateSimple(\n votes: ReadonlyMap<string, Vote>,\n buildReasoningFn: (\n decision: 'approve' | 'reject' | 'no_consensus',\n effectiveVotes: number,\n downweightedAgents: string[],\n method: 'ow' | 'isp' | 'simple'\n ) => string\n): HigherOrderVotingResult {\n let approve = 0;\n let reject = 0;\n let total = 0;\n\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') {\n approve++;\n } else if (vote.decision === 'reject') {\n reject++;\n }\n if (vote.decision !== 'abstain') {\n total++;\n }\n }\n\n const posteriorApproval = total > 0 ? approve / total : 0.5;\n const posteriorRejection = total > 0 ? reject / total : 0.5;\n const decision = determineHigherOrderDecision(posteriorApproval, posteriorRejection);\n\n return {\n decision,\n posteriorApproval,\n posteriorRejection,\n effectiveVoteCount: total,\n usedCorrelationData: false,\n method: 'simple',\n improvementOverBaseline: 0,\n downweightedAgents: [],\n reasoning: buildReasoningFn(decision, total, [], 'simple'),\n };\n}\n\n/**\n * Calculate improvement over baseline.\n */\nexport function calculateImprovement(\n posteriorApproval: number,\n posteriorRejection: number,\n decision: 'approve' | 'reject' | 'no_consensus',\n baseline: HigherOrderVotingResult\n): number {\n // Improvement is measured by increased confidence in the same direction\n if (decision === 'no_consensus' || baseline.decision === 'no_consensus') {\n return 0;\n }\n\n const currentConfidence = decision === 'approve' ? posteriorApproval : posteriorRejection;\n const baselineConfidence =\n baseline.decision === 'approve' ? baseline.posteriorApproval : baseline.posteriorRejection;\n\n // Return improvement as percentage points\n return (currentConfidence - baselineConfidence) * 100;\n}\n\n/**\n * Build reasoning string for voting result.\n */\nexport function buildReasoning(\n decision: 'approve' | 'reject' | 'no_consensus',\n effectiveVotes: number,\n downweightedAgents: readonly string[],\n method: 'ow' | 'isp' | 'simple'\n): string {\n const methodName =\n method === 'ow'\n ? 'Opinion-Wise Bayesian aggregation'\n : method === 'isp'\n ? 'Independent Subset Partition'\n : 'simple majority voting';\n\n let reasoning = `Decision reached via ${methodName} with ${effectiveVotes.toFixed(1)} effective votes. `;\n\n if (downweightedAgents.length > 0) {\n reasoning += `${String(downweightedAgents.length)} agent(s) downweighted due to correlation. `;\n }\n\n if (decision === 'no_consensus') {\n reasoning += 'No consensus reached due to insufficient margin.';\n } else {\n reasoning += `Final decision: ${decision}.`;\n }\n\n return reasoning;\n}\n","/**\n * nexus-agents/consensus - Higher-Order Voting Implementation\n *\n * Implements Opinion-Wise (OW) and Independent Subset Partition (ISP) voting\n * methods that account for correlations between agent opinions.\n *\n * Traditional voting assumes independence between voters. Higher-order voting\n * uses Bayesian-optimal aggregation that handles correlated agents better,\n * resulting in more accurate consensus decisions.\n *\n * @module consensus/higher-order-voting\n * (Source: Issue #333)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport type { Vote, VoteCounts } from './types-core.js';\nimport type {\n IHigherOrderVoting,\n ICorrelationTracker,\n CorrelationMatrix,\n HigherOrderVotingConfig,\n HigherOrderVotingResult,\n IndependentSubset,\n} from './higher-order-types.js';\nimport { DEFAULT_HIGHER_ORDER_CONFIG } from './higher-order-types.js';\nimport type { IVotingStrategy, VotingOutcome } from './strategies.js';\nimport type { ConsensusAlgorithm } from './types-core.js';\nimport {\n hasSufficientCorrelationData,\n computeEffectiveWeights,\n bayesianAggregate,\n aggregateSubsets,\n combineSubsetResults,\n determineHigherOrderDecision,\n aggregateSimple,\n calculateImprovement,\n buildReasoning,\n} from './higher-order-helpers.js';\n\nconst logger = createLogger({ component: 'higher-order-voting' });\n\n/** Options for creating OWVoting instance. */\nexport interface OWVotingOptions {\n readonly config?: Partial<HigherOrderVotingConfig>;\n /**\n * Algorithm label this instance reports (#3168). Defaults to `simple_majority`\n * for backward compatibility; `HigherOrderVotingStrategy` sets `opinion_wise`.\n * Keeps the label consistent whether constructed directly or via a factory.\n */\n readonly algorithm?: ConsensusAlgorithm;\n}\n\n/**\n * Opinion-Wise higher-order voting implementation.\n * Uses Bayesian aggregation with correlation awareness.\n */\nexport class OWVoting implements IHigherOrderVoting, IVotingStrategy {\n readonly algorithm: ConsensusAlgorithm;\n private readonly config: HigherOrderVotingConfig;\n\n constructor(options: OWVotingOptions = {}) {\n this.config = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...options.config };\n // #3168: configurable so the label is correct whether built directly or via\n // a factory; defaults to simple_majority for backward compatibility.\n this.algorithm = options.algorithm ?? 'simple_majority';\n logger.info('OWVoting initialized', { config: this.config, algorithm: this.algorithm });\n }\n\n /** IVotingStrategy implementation for integration with ConsensusEngine. */\n calculateOutcome(votes: Map<string, Vote>, _weights?: Map<string, number>): VotingOutcome {\n const result = this.aggregateSimpleInternal(votes);\n return this.toVotingOutcome(votes, result);\n }\n\n aggregateWithCorrelation(\n votes: ReadonlyMap<string, Vote>,\n correlationMatrix: CorrelationMatrix\n ): HigherOrderVotingResult {\n const agentIds = Array.from(votes.keys());\n const hasSufficientData = hasSufficientCorrelationData(agentIds, correlationMatrix);\n\n if (!hasSufficientData && this.config.fallbackToSimpleVoting) {\n // Issue #525: Log at INFO level for visibility\n logger.info('Insufficient correlation data, falling back to simple voting', {\n agentCount: agentIds.length,\n reason: 'insufficient_correlation_data',\n });\n return this.aggregateSimpleInternal(votes);\n }\n\n const effectiveWeights = computeEffectiveWeights(\n agentIds,\n correlationMatrix,\n this.config.correlationThreshold\n );\n\n const { posteriorApproval, posteriorRejection, effectiveVoteCount, downweightedAgents } =\n bayesianAggregate(votes, effectiveWeights);\n\n const decision = determineHigherOrderDecision(posteriorApproval, posteriorRejection);\n const baselineResult = this.aggregateSimpleInternal(votes);\n const improvementOverBaseline = calculateImprovement(\n posteriorApproval,\n posteriorRejection,\n decision,\n baselineResult\n );\n\n const result: HigherOrderVotingResult = {\n decision,\n posteriorApproval,\n posteriorRejection,\n effectiveVoteCount,\n usedCorrelationData: hasSufficientData,\n method: 'ow',\n improvementOverBaseline,\n downweightedAgents,\n reasoning: buildReasoning(decision, effectiveVoteCount, downweightedAgents, 'ow'),\n };\n\n logger.info('OW aggregation complete', {\n decision,\n posteriorApproval: posteriorApproval.toFixed(3),\n effectiveVotes: effectiveVoteCount.toFixed(2),\n downweightedAgents: downweightedAgents.length,\n });\n\n return result;\n }\n\n estimateCorrelation(tracker: ICorrelationTracker): CorrelationMatrix {\n return tracker.computeCorrelationMatrix();\n }\n\n computeISP(\n votes: ReadonlyMap<string, Vote>,\n independentSubsets: readonly IndependentSubset[]\n ): HigherOrderVotingResult {\n if (independentSubsets.length === 0) {\n // Issue #525: Log at INFO level for visibility\n logger.info('No independent subsets, falling back to simple voting', {\n reason: 'no_independent_subsets',\n });\n return this.aggregateSimpleInternal(votes);\n }\n\n const { subsetResults, downweightedAgents } = aggregateSubsets(votes, independentSubsets);\n const { posteriorApproval, posteriorRejection } = combineSubsetResults(subsetResults);\n const effectiveVoteCount = independentSubsets.length;\n const decision = determineHigherOrderDecision(posteriorApproval, posteriorRejection);\n\n const baselineResult = this.aggregateSimpleInternal(votes);\n const improvementOverBaseline = calculateImprovement(\n posteriorApproval,\n posteriorRejection,\n decision,\n baselineResult\n );\n\n const result: HigherOrderVotingResult = {\n decision,\n posteriorApproval,\n posteriorRejection,\n effectiveVoteCount,\n usedCorrelationData: true,\n method: 'isp',\n improvementOverBaseline,\n independentSubsets,\n downweightedAgents,\n reasoning: buildReasoning(decision, effectiveVoteCount, downweightedAgents, 'isp'),\n };\n\n logger.info('ISP aggregation complete', {\n decision,\n subsetCount: independentSubsets.length,\n posteriorApproval: posteriorApproval.toFixed(3),\n });\n\n return result;\n }\n\n aggregate(\n votes: ReadonlyMap<string, Vote>,\n tracker: ICorrelationTracker\n ): HigherOrderVotingResult {\n const agentIds = Array.from(votes.keys());\n\n if (!tracker.hasSufficientData(agentIds)) {\n if (this.config.fallbackToSimpleVoting) {\n // Issue #525: Log at INFO level for visibility\n logger.info('Insufficient data for correlation analysis, using simple voting', {\n agentCount: agentIds.length,\n reason: 'insufficient_tracker_data',\n });\n return this.aggregateSimpleInternal(votes);\n }\n }\n\n const correlationMatrix = tracker.computeCorrelationMatrix();\n const owResult = this.aggregateWithCorrelation(votes, correlationMatrix);\n\n const independentSubsets = tracker.identifyIndependentSubsets();\n if (independentSubsets.length > 1) {\n const ispResult = this.computeISP(votes, independentSubsets);\n const owConfidence = Math.abs(owResult.posteriorApproval - 0.5) * 2;\n const ispConfidence = Math.abs(ispResult.posteriorApproval - 0.5) * 2;\n\n if (ispConfidence > owConfidence) {\n logger.debug('Using ISP result over OW due to higher confidence');\n return ispResult;\n }\n }\n\n return owResult;\n }\n\n getConfig(): HigherOrderVotingConfig {\n return { ...this.config };\n }\n\n private aggregateSimpleInternal(votes: ReadonlyMap<string, Vote>): HigherOrderVotingResult {\n return aggregateSimple(votes, buildReasoning);\n }\n\n private toVotingOutcome(\n votes: Map<string, Vote>,\n result: HigherOrderVotingResult\n ): VotingOutcome {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') approve++;\n else if (vote.decision === 'reject') reject++;\n else abstain++;\n }\n\n const voteCounts: VoteCounts = { approve, reject, abstain, total: votes.size };\n\n const rawPercentage = result.posteriorApproval * 100;\n const approvalPercentage = Number.isFinite(rawPercentage) ? rawPercentage : 0;\n\n return {\n approved: result.decision === 'approve',\n approvalPercentage,\n voteCounts,\n reason: result.reasoning,\n };\n }\n}\n\n/** Creates a new OWVoting instance. */\nexport function createOWVoting(options?: OWVotingOptions): IHigherOrderVoting {\n return new OWVoting(options);\n}\n\n/**\n * Higher-order voting strategy for integration with VotingStrategyFactory.\n * Wraps OWVoting to provide IVotingStrategy interface.\n */\nexport class HigherOrderVotingStrategy extends OWVoting implements IVotingStrategy {\n constructor(options: OWVotingOptions = {}) {\n // #3168: set the algorithm label via the constructor so it survives\n // regardless of how the instance is created (no field-override divergence).\n super({ ...options, algorithm: options.algorithm ?? 'opinion_wise' });\n }\n}\n\n/** Creates a higher-order voting strategy for use with ConsensusEngine. */\nexport function createHigherOrderVotingStrategy(\n options?: OWVotingOptions\n): HigherOrderVotingStrategy {\n return new HigherOrderVotingStrategy(options);\n}\n","/**\n * nexus-agents/consensus - Voting Strategies\n *\n * Implementation of different voting strategies for consensus engine.\n * Supports simple majority, supermajority, unanimous, and proof-of-learning.\n */\n\nimport type {\n ConsensusAlgorithm,\n Vote,\n VoteCounts,\n WeightedVoteCounts,\n AgentPerformance,\n} from './types.js';\nimport { VOTING_THRESHOLDS } from './types.js';\nimport { HigherOrderVotingStrategy } from './higher-order-voting.js';\n\n/**\n * Interface for voting strategy implementations.\n */\nexport interface IVotingStrategy {\n readonly algorithm: ConsensusAlgorithm;\n calculateOutcome(votes: Map<string, Vote>, weights?: Map<string, number>): VotingOutcome;\n}\n\n/**\n * Result of a voting strategy calculation.\n */\nexport interface VotingOutcome {\n approved: boolean;\n approvalPercentage: number;\n voteCounts: VoteCounts;\n weightedCounts?: WeightedVoteCounts;\n reason: string;\n}\n\n/**\n * Evaluates an approval ratio against a threshold — the shared math behind\n * the simple-majority, supermajority and proof-of-learning strategies.\n *\n * `inclusive` selects the comparison: `>=` for supermajority (67% passes at\n * exactly 67%), strict `>` for simple-majority and proof-of-learning (a tie\n * at the threshold is not enough). Callers apply their own zero-denominator\n * guard before calling this.\n */\nfunction evaluateThreshold(\n approveCount: number,\n votingTotal: number,\n threshold: number,\n inclusive: boolean\n): { approved: boolean; approvalPercentage: number } {\n const ratio = approveCount / votingTotal;\n return {\n approved: inclusive ? ratio >= threshold : ratio > threshold,\n approvalPercentage: ratio * 100,\n };\n}\n\n/**\n * Base voting strategy with common functionality.\n */\nabstract class BaseVotingStrategy implements IVotingStrategy {\n abstract readonly algorithm: ConsensusAlgorithm;\n\n abstract calculateOutcome(votes: Map<string, Vote>, weights?: Map<string, number>): VotingOutcome;\n\n /**\n * Count votes by decision type.\n */\n protected countVotes(votes: Map<string, Vote>): VoteCounts {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n\n for (const vote of votes.values()) {\n switch (vote.decision) {\n case 'approve':\n approve++;\n break;\n case 'reject':\n reject++;\n break;\n case 'abstain':\n abstain++;\n break;\n }\n }\n\n return { approve, reject, abstain, total: votes.size };\n }\n\n /**\n * Calculate weighted vote counts using agent performance weights.\n */\n protected countWeightedVotes(\n votes: Map<string, Vote>,\n weights: Map<string, number>\n ): WeightedVoteCounts {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n let totalWeight = 0;\n\n for (const [agentId, vote] of votes.entries()) {\n const weight = weights.get(agentId) ?? 1.0;\n totalWeight += weight;\n\n switch (vote.decision) {\n case 'approve':\n approve += weight;\n break;\n case 'reject':\n reject += weight;\n break;\n case 'abstain':\n abstain += weight;\n break;\n }\n }\n\n return { approve, reject, abstain, totalWeight };\n }\n}\n\n/**\n * Simple majority voting strategy (>50% approval).\n */\nexport class SimpleMajorityStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'simple_majority';\n\n calculateOutcome(votes: Map<string, Vote>): VotingOutcome {\n const counts = this.countVotes(votes);\n const votingVotes = counts.approve + counts.reject; // Abstains don't count\n const threshold = VOTING_THRESHOLDS.simple_majority;\n\n if (votingVotes === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No votes cast (excluding abstentions)',\n };\n }\n\n const { approved, approvalPercentage } = evaluateThreshold(\n counts.approve,\n votingVotes,\n threshold,\n false\n );\n\n return {\n approved,\n approvalPercentage,\n voteCounts: counts,\n reason: approved\n ? `Approved with ${approvalPercentage.toFixed(1)}% (>${String(threshold * 100)}% required)`\n : `Rejected with ${approvalPercentage.toFixed(1)}% (<=${String(threshold * 100)}% threshold)`,\n };\n }\n}\n\n/**\n * Supermajority voting strategy (>=67% approval).\n */\nexport class SupermajorityStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'supermajority';\n\n calculateOutcome(votes: Map<string, Vote>): VotingOutcome {\n const counts = this.countVotes(votes);\n const votingVotes = counts.approve + counts.reject;\n const threshold = VOTING_THRESHOLDS.supermajority;\n\n if (votingVotes === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No votes cast (excluding abstentions)',\n };\n }\n\n const { approved, approvalPercentage } = evaluateThreshold(\n counts.approve,\n votingVotes,\n threshold,\n true\n );\n\n return {\n approved,\n approvalPercentage,\n voteCounts: counts,\n reason: approved\n ? `Approved with ${approvalPercentage.toFixed(1)}% (>=${String(threshold * 100)}% required)`\n : `Rejected with ${approvalPercentage.toFixed(1)}% (<${String(threshold * 100)}% threshold)`,\n };\n }\n}\n\n/**\n * Unanimous voting strategy (100% approval required).\n */\nexport class UnanimousStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'unanimous';\n\n calculateOutcome(votes: Map<string, Vote>): VotingOutcome {\n const counts = this.countVotes(votes);\n\n if (counts.total === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No votes cast',\n };\n }\n\n // For unanimous, any rejection fails the proposal\n // Abstentions are allowed but don't count toward approval\n const approvalPercentage = counts.total > 0 ? (counts.approve / counts.total) * 100 : 0;\n\n if (counts.reject > 0) {\n return {\n approved: false,\n approvalPercentage,\n voteCounts: counts,\n reason: `Rejected: ${String(counts.reject)} rejection(s) cast (unanimous approval required)`,\n };\n }\n\n if (counts.approve === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n reason: 'No approvals cast (at least one approval required)',\n };\n }\n\n return {\n approved: true,\n approvalPercentage,\n voteCounts: counts,\n reason: `Unanimously approved with ${String(counts.approve)} vote(s)`,\n };\n }\n}\n\n/**\n * Proof-of-learning weighted voting strategy.\n * Agents with better track records have more voting power.\n */\nexport class ProofOfLearningStrategy extends BaseVotingStrategy {\n readonly algorithm: ConsensusAlgorithm = 'proof_of_learning';\n\n calculateOutcome(votes: Map<string, Vote>, weights?: Map<string, number>): VotingOutcome {\n const counts = this.countVotes(votes);\n const effectiveWeights = weights ?? new Map<string, number>();\n const weightedCounts = this.countWeightedVotes(votes, effectiveWeights);\n const threshold = VOTING_THRESHOLDS.proof_of_learning;\n\n const votingWeight = weightedCounts.approve + weightedCounts.reject;\n\n if (votingWeight === 0) {\n return {\n approved: false,\n approvalPercentage: 0,\n voteCounts: counts,\n weightedCounts,\n reason: 'No weighted votes cast (excluding abstentions)',\n };\n }\n\n const { approved, approvalPercentage } = evaluateThreshold(\n weightedCounts.approve,\n votingWeight,\n threshold,\n false\n );\n\n return {\n approved,\n approvalPercentage,\n voteCounts: counts,\n weightedCounts,\n reason: approved\n ? `Approved with ${approvalPercentage.toFixed(1)}% weighted approval`\n : `Rejected with ${approvalPercentage.toFixed(1)}% weighted approval`,\n };\n }\n}\n\n/**\n * Calculate vote weight for an agent based on their performance history.\n * Weight ranges from 0.5 (no history) to 1.0 (perfect track record).\n */\nexport function calculateVoteWeight(performance: AgentPerformance | undefined): number {\n if (performance === undefined || performance.totalVotes === 0) {\n return 1.0; // Default weight for new agents\n }\n\n // Weight = 0.5 + (successRate * 0.5)\n // This gives a range of 0.5 to 1.0 based on historical accuracy\n return 0.5 + performance.successRate * 0.5;\n}\n\n/**\n * Factory for creating voting strategies.\n */\nexport class VotingStrategyFactory {\n private readonly strategies: Map<ConsensusAlgorithm, IVotingStrategy>;\n\n constructor() {\n this.strategies = new Map<ConsensusAlgorithm, IVotingStrategy>([\n ['simple_majority', new SimpleMajorityStrategy()],\n ['supermajority', new SupermajorityStrategy()],\n ['unanimous', new UnanimousStrategy()],\n ['proof_of_learning', new ProofOfLearningStrategy()],\n ['opinion_wise', new HigherOrderVotingStrategy()],\n ['higher_order', new HigherOrderVotingStrategy()],\n ]);\n }\n\n /**\n * Get a voting strategy by algorithm type.\n */\n getStrategy(algorithm: ConsensusAlgorithm): IVotingStrategy {\n const strategy = this.strategies.get(algorithm);\n if (strategy === undefined) {\n throw new Error(`Unknown voting algorithm: ${algorithm}`);\n }\n return strategy;\n }\n\n /**\n * Register a custom voting strategy.\n */\n registerStrategy(strategy: IVotingStrategy): void {\n this.strategies.set(strategy.algorithm, strategy);\n }\n\n /**\n * Get all available algorithm types.\n */\n getAvailableAlgorithms(): ConsensusAlgorithm[] {\n return Array.from(this.strategies.keys());\n }\n}\n\n/**\n * Creates a voting strategy factory with default strategies.\n */\nexport function createStrategyFactory(): VotingStrategyFactory {\n return new VotingStrategyFactory();\n}\n","/**\n * nexus-agents/consensus - Result Builder\n *\n * Helper functions for building consensus results.\n */\n\nimport { getTimeProvider } from '../core/index.js';\nimport type {\n ProposalId,\n ProposalState,\n ConsensusResult,\n ProposalStatus,\n ConsensusEngineConfig,\n} from './types.js';\nimport type { VotingOutcome } from './strategies.js';\n\n/**\n * Build a pending result for an active proposal.\n */\nexport function buildPendingResult(\n state: ProposalState,\n proposalId: ProposalId,\n outcome: VotingOutcome,\n config: ConsensusEngineConfig\n): ConsensusResult {\n const now = new Date(getTimeProvider().now());\n return {\n proposalId,\n proposal: state.proposal,\n outcome: state.status === 'voting' ? 'pending' : state.status,\n votes: new Map(state.votes),\n voteCounts: outcome.voteCounts,\n weightedCounts: outcome.weightedCounts,\n approvalPercentage: outcome.approvalPercentage,\n quorumReached: state.votes.size >= config.minVotersForQuorum,\n startedAt: state.startedAt.toISOString(),\n closedAt: now.toISOString(),\n durationMs: now.getTime() - state.startedAt.getTime(),\n };\n}\n\n/**\n * Build a final result for a closed proposal.\n */\nexport function buildFinalResult(\n state: ProposalState,\n proposalId: ProposalId,\n outcome: VotingOutcome,\n config: ConsensusEngineConfig\n): ConsensusResult {\n const now = new Date(getTimeProvider().now());\n const quorumReached = state.votes.size >= config.minVotersForQuorum;\n const finalStatus = determineFinalStatus(quorumReached, outcome.approved);\n\n return {\n proposalId,\n proposal: state.proposal,\n outcome: finalStatus,\n votes: new Map(state.votes),\n voteCounts: outcome.voteCounts,\n weightedCounts: outcome.weightedCounts,\n approvalPercentage: outcome.approvalPercentage,\n quorumReached,\n startedAt: state.startedAt.toISOString(),\n closedAt: now.toISOString(),\n durationMs: now.getTime() - state.startedAt.getTime(),\n };\n}\n\n/**\n * Build a timeout result for an expired proposal.\n */\nexport function buildTimeoutResult(\n state: ProposalState,\n proposalId: ProposalId,\n outcome: VotingOutcome,\n config: ConsensusEngineConfig\n): ConsensusResult {\n const now = new Date(getTimeProvider().now());\n return {\n proposalId,\n proposal: state.proposal,\n outcome: 'timeout',\n votes: new Map(state.votes),\n voteCounts: outcome.voteCounts,\n weightedCounts: outcome.weightedCounts,\n approvalPercentage: outcome.approvalPercentage,\n quorumReached: state.votes.size >= config.minVotersForQuorum,\n startedAt: state.startedAt.toISOString(),\n closedAt: now.toISOString(),\n durationMs: now.getTime() - state.startedAt.getTime(),\n };\n}\n\n/**\n * Determine final status based on quorum and approval.\n */\nexport function determineFinalStatus(quorumReached: boolean, approved: boolean): ProposalStatus {\n if (!quorumReached || !approved) return 'rejected';\n return 'approved';\n}\n","/**\n * nexus-agents/consensus - Helper Functions\n *\n * Utility functions for the consensus engine.\n */\n\nimport type { ProposalId } from './types.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\n\n/**\n * Generate a unique proposal ID.\n */\nexport function generateProposalId(): ProposalId {\n const timestamp = getTimeProvider().now().toString(36);\n const random = getRandomProvider().random().toString(36).substring(2, 8);\n return `prop_${timestamp}_${random}`;\n}\n","/**\n * nexus-agents/consensus - Incremental Quorum\n *\n * Detects ambiguous voting scenarios and triggers voter pool expansion.\n * Complements agreement-based cascading (early termination when certain)\n * with expansion when uncertain.\n *\n * (Source: Issue #1408 — Incremental Quorum for Consensus Robustness)\n *\n * @module consensus/incremental-quorum\n */\n\nimport type { Vote } from './types.js';\n\n/**\n * Parameters for ambiguity detection.\n */\nexport interface AmbiguityParams {\n /** Minimum average confidence to avoid expansion. */\n readonly confidenceThreshold: number;\n /** If approval rate is within this band of the threshold, consider ambiguous. */\n readonly ambiguityBand: number;\n}\n\n/**\n * Determines if the current voting state is ambiguous.\n *\n * Ambiguity is detected when:\n * 1. Approval rate is within the ambiguity band of the threshold, OR\n * 2. Average voter confidence is below the confidence threshold\n *\n * @param votes - Current vote map\n * @param totalExpected - Total expected voters\n * @param threshold - Algorithm-specific approval threshold (0-1)\n * @param params - Ambiguity detection parameters\n * @returns true if the voting state is ambiguous\n */\nexport function isVotingAmbiguous(\n votes: ReadonlyMap<string, Vote>,\n totalExpected: number,\n threshold: number,\n params: AmbiguityParams\n): boolean {\n if (votes.size === 0) return false;\n\n let approvals = 0;\n let totalConfidence = 0;\n for (const vote of votes.values()) {\n if (vote.decision === 'approve') approvals++;\n totalConfidence += vote.confidence;\n }\n\n const approvalRate = approvals / totalExpected;\n const avgConfidence = totalConfidence / votes.size;\n\n // Check if approval rate is within the ambiguity band of threshold\n const lowerBand = threshold - params.ambiguityBand;\n const upperBand = threshold + params.ambiguityBand;\n const rateAmbiguous = approvalRate >= lowerBand && approvalRate <= upperBand;\n\n // Check if confidence is too low\n const confidenceAmbiguous = avgConfidence < params.confidenceThreshold;\n\n return rateAmbiguous || confidenceAmbiguous;\n}\n","/* eslint-disable max-lines */\n// 426 lines — cohesive single-concern engine. Per governance, 400-600 OK if cohesive.\n\n/**\n * nexus-agents/consensus - Consensus Engine\n *\n * Core consensus engine implementation supporting multiple voting strategies.\n * Manages proposal lifecycle, vote collection, and outcome determination.\n */\n\nimport type { Result, ILogger } from '../core/index.js';\nimport { ok, err, AgentError, createLogger, getTimeProvider } from '../core/index.js';\nimport type {\n Proposal,\n ProposalId,\n Vote,\n ConsensusResult,\n ConsensusAlgorithm,\n AgentPerformance,\n ConsensusEngineConfig,\n ProposalState,\n ConsensusMetrics,\n ProposalCacheConfig,\n IncrementalQuorumConfig,\n VoterExpansionCallback,\n} from './types.js';\nimport {\n ProposalSchema,\n VoteSchema,\n DEFAULT_CONSENSUS_CONFIG,\n VOTING_THRESHOLDS,\n DEFAULT_INCREMENTAL_QUORUM_CONFIG,\n} from './types.js';\nimport { VotingStrategyFactory, calculateVoteWeight, type VotingOutcome } from './strategies.js';\nimport { buildFinalResult, buildTimeoutResult, buildPendingResult } from './result-builder.js';\nimport { generateProposalId } from './helpers.js';\nimport { isVotingAmbiguous } from './incremental-quorum.js';\n\n/**\n * Error class for consensus-related failures.\n */\nexport class ConsensusError extends AgentError {\n constructor(message: string, context?: Record<string, unknown>) {\n super(message, context !== undefined ? { context } : {});\n this.name = 'ConsensusError';\n }\n}\n\n/**\n * Interface for the consensus engine.\n */\nexport interface IConsensusEngine {\n propose(proposal: Proposal): Promise<Result<ProposalId, ConsensusError>>;\n vote(proposalId: ProposalId, agentId: string, vote: Vote): Promise<Result<void, ConsensusError>>;\n getResult(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>>;\n close(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>>;\n getMetrics(): ConsensusMetrics;\n}\n\ninterface InternalMetrics {\n totalProposals: number;\n approvedProposals: number;\n rejectedProposals: number;\n timedOutProposals: number;\n totalDurationMs: number;\n totalVotes: number;\n algorithmUsage: Record<ConsensusAlgorithm, number>;\n}\n\n/**\n * Cache entry for proposal content-based caching (Issue #589).\n */\ninterface ProposalCacheEntry {\n readonly proposalId: ProposalId;\n readonly result: ConsensusResult;\n readonly cachedAt: number;\n}\n\n/**\n * Default proposal cache configuration.\n * Enabled by default to improve determinism (fitness audit recommendation).\n */\n/**\n * Hypothetical-vote stand-ins used by {@link ConsensusEngine.canCascadeEarly}\n * to probe the strategy's outcome under best/worst-case pending votes.\n * The actual `confidence` and `reasoning` fields are never inspected by\n * `IVotingStrategy.calculateOutcome` (all strategies count by `decision`),\n * but must satisfy `VoteSchema` (confidence in [0,1], reasoning non-empty).\n */\nconst HYPOTHETICAL_APPROVE: Vote = {\n decision: 'approve',\n confidence: 0.5,\n reasoning: 'hypothetical-cascade-probe',\n};\nconst HYPOTHETICAL_REJECT: Vote = {\n decision: 'reject',\n confidence: 0.5,\n reasoning: 'hypothetical-cascade-probe',\n};\n\nconst DEFAULT_PROPOSAL_CACHE_CONFIG: ProposalCacheConfig = {\n enabled: true,\n ttlMs: 3600000, // 1 hour\n maxEntries: 500,\n};\n\n/**\n * Consensus engine for multi-agent decision making.\n *\n * @example\n * ```typescript\n * const engine = new ConsensusEngine({ defaultTimeout: 30000 });\n * const proposalResult = await engine.propose({\n * title: 'Use microservices architecture',\n * description: 'Proposal to adopt microservices',\n * algorithm: 'supermajority',\n * });\n * if (proposalResult.ok) {\n * await engine.vote(proposalResult.value, 'agent-1', {\n * decision: 'approve',\n * confidence: 0.9,\n * reasoning: 'Good for scalability',\n * });\n * }\n * ```\n */\nexport class ConsensusEngine implements IConsensusEngine {\n private readonly proposals: Map<ProposalId, ProposalState> = new Map();\n private readonly closedProposals: Map<ProposalId, ConsensusResult> = new Map();\n private readonly agentPerformance: Map<string, AgentPerformance> = new Map();\n private readonly proposalContentCache: Map<string, ProposalCacheEntry> = new Map();\n private readonly strategyFactory: VotingStrategyFactory;\n private readonly config: ConsensusEngineConfig;\n private readonly cacheConfig: ProposalCacheConfig;\n private readonly quorumConfig: IncrementalQuorumConfig;\n private readonly logger: ILogger;\n private readonly metrics: InternalMetrics;\n private voterExpansionCallback?: VoterExpansionCallback;\n\n constructor(config?: Partial<ConsensusEngineConfig>, logger?: ILogger) {\n this.config = { ...DEFAULT_CONSENSUS_CONFIG, ...config };\n this.cacheConfig = { ...DEFAULT_PROPOSAL_CACHE_CONFIG, ...config?.proposalCache };\n this.quorumConfig = { ...DEFAULT_INCREMENTAL_QUORUM_CONFIG, ...config?.incrementalQuorum };\n this.logger = logger ?? createLogger({ component: 'ConsensusEngine' });\n this.strategyFactory = new VotingStrategyFactory();\n this.metrics = this.createInitialMetrics();\n }\n\n /**\n * Sets the callback for incremental quorum voter expansion (Issue #1408).\n * When ambiguous votes are detected, this callback requests additional voters.\n */\n setVoterExpansionCallback(callback: VoterExpansionCallback): void {\n this.voterExpansionCallback = callback;\n }\n\n propose(proposal: Proposal): Promise<Result<ProposalId, ConsensusError>> {\n const validation = ProposalSchema.safeParse(proposal);\n if (!validation.success) {\n return Promise.resolve(\n err(\n new ConsensusError(`Invalid proposal: ${validation.error.message}`, {\n errors: validation.error.issues,\n })\n )\n );\n }\n\n // Check cache for identical proposal content (Issue #589)\n if (this.cacheConfig.enabled) {\n const cachedEntry = this.getCachedResult(validation.data);\n if (cachedEntry !== undefined) {\n this.logger.debug('Returning cached proposal result', {\n cachedProposalId: cachedEntry.proposalId,\n cachedOutcome: cachedEntry.result.outcome,\n });\n return Promise.resolve(ok(cachedEntry.proposalId));\n }\n }\n\n if (this.proposals.size >= this.config.maxActiveProposals) {\n return Promise.resolve(\n err(\n new ConsensusError(\n `Maximum active proposals (${String(this.config.maxActiveProposals)}) reached`\n )\n )\n );\n }\n\n const proposalId = proposal.id ?? generateProposalId();\n const state = this.createProposalState(validation.data, proposalId);\n this.setupTimeout(state, proposalId, proposal.timeout);\n this.registerProposal(proposalId, state, proposal.algorithm);\n return Promise.resolve(ok(proposalId));\n }\n\n async vote(\n proposalId: ProposalId,\n agentId: string,\n vote: Vote\n ): Promise<Result<void, ConsensusError>> {\n const validationErr = this.validateVote(vote);\n if (validationErr !== undefined) return err(validationErr);\n\n const stateErr = this.validateProposalState(proposalId);\n if (stateErr !== undefined) return err(stateErr);\n\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n return err(new ConsensusError(`Proposal ${proposalId} not found`));\n }\n\n this.recordVote(state, agentId, vote);\n\n // Agreement-based cascade always takes priority\n if (this.canCascadeEarly(state)) {\n return this.closeInternal(proposalId).then((r) => (r.ok ? ok(undefined) : err(r.error)));\n }\n\n // All required voters voted — check for incremental quorum expansion\n if (this.allRequiredVotersVoted(state)) {\n // Re-entry guard (#2861): `tryExpandQuorum` awaits its callback and\n // then mutates `state.proposal.requiredVoters` / `expansionRounds`.\n // A concurrent `vote()` that also sees `allRequiredVotersVoted`\n // must NOT start a second expansion — that would invoke the\n // expansion callback twice and clobber the first expansion's\n // voter list. This vote is already recorded; return ok and let\n // the in-flight expansion settle.\n if (state.expansionInFlight === true) {\n return Promise.resolve(ok(undefined));\n }\n state.expansionInFlight = true;\n let expanded: boolean;\n try {\n expanded = await this.tryExpandQuorum(proposalId, state);\n } finally {\n state.expansionInFlight = false;\n }\n if (!expanded) {\n return this.closeInternal(proposalId).then((r) => (r.ok ? ok(undefined) : err(r.error)));\n }\n // Expansion succeeded — wait for new voters\n }\n\n return Promise.resolve(ok(undefined));\n }\n\n getResult(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>> {\n const closedResult = this.closedProposals.get(proposalId);\n if (closedResult !== undefined) return Promise.resolve(ok(closedResult));\n\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n return Promise.resolve(err(new ConsensusError(`Proposal ${proposalId} not found`)));\n }\n\n const outcome = this.calculateOutcome(state);\n return Promise.resolve(ok(buildPendingResult(state, proposalId, outcome, this.config)));\n }\n\n close(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>> {\n return this.closeInternal(proposalId);\n }\n\n getMetrics(): ConsensusMetrics {\n const completed =\n this.metrics.approvedProposals +\n this.metrics.rejectedProposals +\n this.metrics.timedOutProposals;\n return {\n totalProposals: this.metrics.totalProposals,\n approvedProposals: this.metrics.approvedProposals,\n rejectedProposals: this.metrics.rejectedProposals,\n timedOutProposals: this.metrics.timedOutProposals,\n averageDurationMs: completed > 0 ? this.metrics.totalDurationMs / completed : 0,\n averageVotesPerProposal: completed > 0 ? this.metrics.totalVotes / completed : 0,\n algorithmUsage: { ...this.metrics.algorithmUsage },\n };\n }\n\n updateAgentPerformance(agentId: string, wasCorrect: boolean): void {\n const existing = this.agentPerformance.get(agentId);\n const now = getTimeProvider().nowIso();\n\n if (existing === undefined) {\n this.agentPerformance.set(agentId, {\n agentId,\n totalVotes: 1,\n correctVotes: wasCorrect ? 1 : 0,\n successRate: wasCorrect ? 1.0 : 0.0,\n lastUpdated: now,\n });\n } else {\n const totalVotes = existing.totalVotes + 1;\n const correctVotes = existing.correctVotes + (wasCorrect ? 1 : 0);\n this.agentPerformance.set(agentId, {\n agentId,\n totalVotes,\n correctVotes,\n successRate: correctVotes / totalVotes,\n lastUpdated: now,\n });\n }\n }\n\n getAgentPerformance(agentId: string): AgentPerformance | undefined {\n return this.agentPerformance.get(agentId);\n }\n\n getActiveProposalCount(): number {\n return this.proposals.size;\n }\n\n private createProposalState(data: Proposal, proposalId: ProposalId): ProposalState {\n const now = new Date(getTimeProvider().now());\n return {\n proposal: { ...data, id: proposalId, createdAt: now.toISOString() },\n status: 'voting',\n votes: new Map(),\n voteWeights: new Map(),\n startedAt: now,\n };\n }\n\n private setupTimeout(state: ProposalState, proposalId: ProposalId, timeout?: number): void {\n const timeoutMs = timeout ?? this.config.defaultTimeout;\n state.timeoutId = setTimeout(() => {\n this.handleTimeout(proposalId);\n }, timeoutMs);\n }\n\n private registerProposal(\n proposalId: ProposalId,\n state: ProposalState,\n algorithm: ConsensusAlgorithm\n ): void {\n this.proposals.set(proposalId, state);\n this.metrics.totalProposals++;\n this.metrics.algorithmUsage[algorithm]++;\n this.logger.info('Proposal created', {\n proposalId,\n title: state.proposal.title,\n algorithm,\n timeout: this.config.defaultTimeout,\n });\n }\n\n private validateVote(vote: Vote): ConsensusError | undefined {\n const validation = VoteSchema.safeParse(vote);\n if (!validation.success) {\n return new ConsensusError(`Invalid vote: ${validation.error.message}`, {\n errors: validation.error.issues,\n });\n }\n return undefined;\n }\n\n private validateProposalState(proposalId: ProposalId): ConsensusError | undefined {\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n if (this.closedProposals.has(proposalId)) {\n return new ConsensusError(`Proposal ${proposalId} is already closed`);\n }\n return new ConsensusError(`Proposal ${proposalId} not found`);\n }\n if (state.status !== 'voting') {\n return new ConsensusError(`Proposal ${proposalId} is not accepting votes`, {\n status: state.status,\n });\n }\n return undefined;\n }\n\n private recordVote(state: ProposalState, agentId: string, vote: Vote): void {\n state.votes.set(agentId, {\n ...vote,\n timestamp: getTimeProvider().nowIso(),\n });\n if (state.proposal.algorithm === 'proof_of_learning') {\n const performance = this.agentPerformance.get(agentId);\n state.voteWeights.set(agentId, calculateVoteWeight(performance));\n }\n this.logger.debug('Vote recorded', {\n proposalId: state.proposal.id,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n });\n }\n\n private closeInternal(proposalId: ProposalId): Promise<Result<ConsensusResult, ConsensusError>> {\n const state = this.proposals.get(proposalId);\n if (state === undefined) {\n const closed = this.closedProposals.get(proposalId);\n if (closed !== undefined) return Promise.resolve(ok(closed));\n return Promise.resolve(err(new ConsensusError(`Proposal ${proposalId} not found`)));\n }\n\n if (state.timeoutId !== undefined) clearTimeout(state.timeoutId);\n\n const outcome = this.calculateOutcome(state);\n const result = buildFinalResult(state, proposalId, outcome, this.config);\n this.finalize(proposalId, result, state.votes.size);\n return Promise.resolve(ok(result));\n }\n\n private handleTimeout(proposalId: ProposalId): void {\n const state = this.proposals.get(proposalId);\n if (state?.status !== 'voting') return;\n\n this.logger.warn('Proposal timed out', { proposalId, voteCount: state.votes.size });\n const outcome = this.calculateOutcome(state);\n const result = buildTimeoutResult(state, proposalId, outcome, this.config);\n this.proposals.delete(proposalId);\n this.addClosedProposal(proposalId, result);\n this.metrics.timedOutProposals++;\n this.metrics.totalDurationMs += result.durationMs;\n this.metrics.totalVotes += state.votes.size;\n }\n\n private finalize(proposalId: ProposalId, result: ConsensusResult, voteCount: number): void {\n this.proposals.delete(proposalId);\n this.addClosedProposal(proposalId, result);\n this.updateMetrics(result);\n\n // Cache successful results for determinism (Issue #589)\n if (\n this.cacheConfig.enabled &&\n (result.outcome === 'approved' || result.outcome === 'rejected')\n ) {\n this.addToCache(result.proposal, proposalId, result);\n }\n\n this.logger.info('Proposal closed', {\n proposalId,\n outcome: result.outcome,\n approvalPercentage: result.approvalPercentage.toFixed(1),\n voteCount,\n quorumReached: result.quorumReached,\n durationMs: result.durationMs,\n });\n }\n\n /**\n * Adds a closed proposal and evicts oldest entries if over limit.\n * Issue #549: Prevent unbounded memory growth in closedProposals Map.\n */\n private addClosedProposal(proposalId: ProposalId, result: ConsensusResult): void {\n // Evict oldest entries if at capacity (Map maintains insertion order)\n while (this.closedProposals.size >= this.config.maxClosedProposals) {\n const firstKey = this.closedProposals.keys().next();\n if (firstKey.done === true) break;\n const oldestKey = firstKey.value;\n this.closedProposals.delete(oldestKey);\n this.logger.debug('Evicted oldest closed proposal', { evictedId: oldestKey });\n }\n this.closedProposals.set(proposalId, result);\n }\n\n private calculateOutcome(state: ProposalState): VotingOutcome {\n const strategy = this.strategyFactory.getStrategy(state.proposal.algorithm);\n const outcome: VotingOutcome = strategy.calculateOutcome(state.votes, state.voteWeights);\n return outcome;\n }\n\n /**\n * Agreement-based cascading: close early when outcome is mathematically determined.\n *\n * #2822: the prior implementation computed approval rates against\n * `totalExpected = requiredVoters.length` and compared against\n * `VOTING_THRESHOLDS[algorithm]` directly. Every voting strategy\n * (`SimpleMajorityStrategy`, `SupermajorityStrategy`, `UnanimousStrategy`,\n * `ProofOfLearningStrategy`) uses `approve + reject` as its denominator —\n * abstains are explicitly excluded. The two diverged whenever abstains\n * were present, producing wrong-winner cascades (e.g. 5-voter supermajority\n * with [approve, abstain, abstain, abstain, pending] cascade-rejected even\n * though the strategy would approve at close).\n *\n * The fix delegates to the strategy itself: build a best-case (all pending\n * voters approve) and worst-case (all pending voters reject) hypothetical\n * vote map, call `strategy.calculateOutcome` on each, and cascade only\n * when both extremes yield the same outcome. This guarantees parity with\n * the strategy's denominator semantics by construction.\n */\n private canCascadeEarly(state: ProposalState): boolean {\n const required = state.proposal.requiredVoters;\n if (required === undefined || required.length === 0) return false;\n if (state.votes.size === 0) return false;\n\n const pending = required.filter((voter) => !state.votes.has(voter));\n if (pending.length === 0) return false; // All voted — handled by allRequiredVotersVoted\n\n const strategy = this.strategyFactory.getStrategy(state.proposal.algorithm);\n\n const bestCase = new Map<string, Vote>(state.votes);\n const worstCase = new Map<string, Vote>(state.votes);\n for (const voter of pending) {\n bestCase.set(voter, HYPOTHETICAL_APPROVE);\n worstCase.set(voter, HYPOTHETICAL_REJECT);\n }\n\n const bestOutcome = strategy.calculateOutcome(bestCase, state.voteWeights);\n const worstOutcome = strategy.calculateOutcome(worstCase, state.voteWeights);\n\n if (bestOutcome.approved !== worstOutcome.approved) return false;\n\n this.logger.info('Agreement cascade: outcome determined', {\n proposalId: state.proposal.id,\n outcome: bestOutcome.approved ? 'approve' : 'reject',\n votesCast: state.votes.size,\n pending: pending.length,\n algorithm: state.proposal.algorithm,\n });\n return true;\n }\n\n private allRequiredVotersVoted(state: ProposalState): boolean {\n const required = state.proposal.requiredVoters;\n if (required === undefined || required.length === 0) return false;\n return required.every((voterId) => state.votes.has(voterId));\n }\n\n /**\n * Attempts incremental quorum expansion when voting is ambiguous (Issue #1408).\n * Returns true if expansion occurred (wait for new voters), false to close immediately.\n */\n private async tryExpandQuorum(proposalId: ProposalId, state: ProposalState): Promise<boolean> {\n if (!this.quorumConfig.enabled) return false;\n if (this.voterExpansionCallback === undefined) return false;\n\n const rounds = state.expansionRounds ?? 0;\n if (rounds >= this.quorumConfig.maxExpansionRounds) return false;\n\n const required = state.proposal.requiredVoters;\n if (required === undefined) return false;\n\n const threshold = VOTING_THRESHOLDS[state.proposal.algorithm];\n const ambiguous = isVotingAmbiguous(state.votes, required.length, threshold, {\n confidenceThreshold: this.quorumConfig.confidenceThreshold,\n ambiguityBand: this.quorumConfig.ambiguityBand,\n });\n\n if (!ambiguous) return false;\n\n let newVoters: readonly string[];\n try {\n newVoters = await this.voterExpansionCallback(\n proposalId,\n required.length,\n this.quorumConfig.votersPerExpansion\n );\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n this.logger.warn('Incremental quorum: expansion callback threw; closing as-is', {\n proposalId,\n errorMessage: error.message,\n });\n return false;\n }\n\n if (newVoters.length === 0) {\n this.logger.info('Incremental quorum: no additional voters available', { proposalId });\n return false;\n }\n\n // Expand the required voters list\n state.proposal.requiredVoters = [...required, ...newVoters];\n state.expansionRounds = rounds + 1;\n\n this.logger.info('Incremental quorum: expanded voter pool', {\n proposalId,\n round: rounds + 1,\n newVoters: newVoters.length,\n totalVoters: state.proposal.requiredVoters.length,\n });\n\n return true;\n }\n\n private updateMetrics(result: ConsensusResult): void {\n this.metrics.totalDurationMs += result.durationMs;\n this.metrics.totalVotes += result.voteCounts.total;\n if (result.outcome === 'approved') this.metrics.approvedProposals++;\n else if (result.outcome === 'rejected') this.metrics.rejectedProposals++;\n else if (result.outcome === 'timeout') this.metrics.timedOutProposals++;\n }\n\n private createInitialMetrics(): InternalMetrics {\n return {\n totalProposals: 0,\n approvedProposals: 0,\n rejectedProposals: 0,\n timedOutProposals: 0,\n totalDurationMs: 0,\n totalVotes: 0,\n algorithmUsage: {\n simple_majority: 0,\n supermajority: 0,\n unanimous: 0,\n proof_of_learning: 0,\n opinion_wise: 0,\n higher_order: 0,\n },\n };\n }\n\n // ============================================================================\n // Proposal Content Caching (Issue #589)\n // ============================================================================\n\n /**\n * Creates a content hash for a proposal to enable cache lookups.\n * Hash is based on title, description, and algorithm (deterministic content).\n */\n private hashProposalContent(proposal: Proposal): string {\n const content = [proposal.title, proposal.description, proposal.algorithm].join('|');\n // Simple FNV-1a hash for fast deterministic hashing\n let hash = 2166136261;\n for (let i = 0; i < content.length; i++) {\n hash ^= content.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0).toString(16);\n }\n\n /**\n * Gets cached result for a proposal if it exists and hasn't expired.\n */\n private getCachedResult(proposal: Proposal): ProposalCacheEntry | undefined {\n const hash = this.hashProposalContent(proposal);\n const cached = this.proposalContentCache.get(hash);\n if (cached === undefined) return undefined;\n\n const now = getTimeProvider().now();\n if (now - cached.cachedAt > this.cacheConfig.ttlMs) {\n this.proposalContentCache.delete(hash);\n this.logger.debug('Cache entry expired', { hash });\n return undefined;\n }\n\n return cached;\n }\n\n /**\n * Adds a proposal result to the cache, evicting oldest entries if needed.\n */\n private addToCache(proposal: Proposal, proposalId: ProposalId, result: ConsensusResult): void {\n const hash = this.hashProposalContent(proposal);\n\n // Evict oldest entries if at capacity (Map maintains insertion order)\n while (this.proposalContentCache.size >= this.cacheConfig.maxEntries) {\n const firstKey = this.proposalContentCache.keys().next();\n if (firstKey.done === true) break;\n const oldestKey = firstKey.value;\n this.proposalContentCache.delete(oldestKey);\n this.logger.debug('Evicted oldest cache entry', { hash: oldestKey });\n }\n\n this.proposalContentCache.set(hash, {\n proposalId,\n result,\n cachedAt: getTimeProvider().now(),\n });\n this.logger.debug('Added proposal to cache', { hash, proposalId });\n }\n\n /**\n * Gets the current cache size (for testing/monitoring).\n */\n getCacheSize(): number {\n return this.proposalContentCache.size;\n }\n\n /**\n * Clears the proposal content cache (for testing/reset).\n */\n clearCache(): void {\n this.proposalContentCache.clear();\n this.logger.debug('Proposal cache cleared');\n }\n}\n\n/**\n * Create a consensus engine with the given configuration.\n *\n * @example\n * ```typescript\n * const engine = createConsensusEngine({\n * defaultTimeout: 60000,\n * maxActiveProposals: 10,\n * });\n * ```\n */\nexport function createConsensusEngine(\n config?: Partial<ConsensusEngineConfig>,\n logger?: ILogger\n): ConsensusEngine {\n return new ConsensusEngine(config, logger);\n}\n","/**\n * Unified Quorum Validator\n *\n * Abstracts quorum validation across VotingProtocol, WeightedVoting, and ConsensusEngine.\n * Per redundancy-analysis.md Section 3.4 - consolidates three quorum implementations.\n *\n * @module consensus/quorum-validator\n * (Source: Issue #576, ADR-0003)\n */\n\nimport { createLogger, formatPercentage, type ILogger } from '../core/index.js';\nimport type { ConsensusAlgorithm, Vote, VoteCounts, WeightedVoteCounts } from './types-core.js';\nimport { SUPERMAJORITY_THRESHOLD } from './types-core.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Agent record for eligibility checks and Byzantine detection.\n */\nexport interface AgentRecord {\n readonly agentId: string;\n readonly weight: number;\n readonly trustScore: number;\n readonly byzantineFlags?: number;\n readonly successRate?: number;\n readonly totalTasks?: number;\n}\n\n/**\n * Quorum validation configuration.\n */\nexport interface QuorumValidationConfig {\n /** Algorithm type */\n readonly algorithm: ConsensusAlgorithm | 'weighted_byzantine';\n /** Numeric threshold (0-1 for percentage, 0-N for weighted sum) */\n readonly threshold: number;\n /** Minimum voters required */\n readonly minVoters: number;\n /** Enable Byzantine detection */\n readonly enableByzantineDetection?: boolean;\n /** Apply confidence multiplier to weights */\n readonly confidenceMultiplier?: boolean;\n /** Include abstentions in quorum calculation */\n readonly includeAbstentions?: boolean;\n}\n\n/**\n * Input for quorum validation.\n */\nexport interface QuorumValidationInput {\n /** Votes cast by agent ID */\n readonly votes: ReadonlyMap<string, Vote>;\n /** Optional: Pre-calculated agent weights */\n readonly agentWeights?: ReadonlyMap<string, number>;\n /** Configuration */\n readonly config: QuorumValidationConfig;\n /** Optional: Agent records for eligibility checks */\n readonly agentRecords?: ReadonlyMap<string, AgentRecord>;\n /** Optional: Required participant count (for ratio-based quorum) */\n readonly requiredParticipants?: number;\n}\n\n/**\n * Quorum validation result (discriminated union).\n */\nexport type QuorumValidationResult =\n | {\n readonly status: 'reached';\n readonly decision: 'approve' | 'reject';\n readonly confidence: number;\n readonly reasoning: string;\n }\n | {\n readonly status: 'not_reached';\n readonly reason: 'insufficient_votes' | 'insufficient_weight' | 'no_consensus';\n readonly details: string;\n }\n | { readonly status: 'invalid'; readonly error: string }\n | { readonly status: 'timeout'; readonly partial: boolean; readonly details: string };\n\n/**\n * Detailed quorum breakdown for observability.\n */\nexport interface QuorumBreakdown {\n readonly totalVotes: number;\n readonly voteCounts: VoteCounts;\n readonly totalWeight: number | undefined;\n readonly weightedCounts: WeightedVoteCounts | undefined;\n readonly threshold: number;\n readonly actualQuorum: number;\n readonly quorumReached: boolean;\n readonly eligibleAgents: readonly string[];\n readonly reasoning: string;\n}\n\n/**\n * Eligibility check result.\n */\nexport type EligibilityResult =\n | { readonly eligible: true; readonly weight: number }\n | {\n readonly eligible: false;\n readonly reason: 'insufficient_weight' | 'low_trust' | 'byzantine_flagged' | 'excluded';\n readonly weight: number;\n };\n\n/**\n * Unified quorum validator interface.\n */\nexport interface IQuorumValidator {\n validateQuorum(input: QuorumValidationInput): QuorumValidationResult;\n getQuorumBreakdown(input: QuorumValidationInput): QuorumBreakdown;\n isAgentEligible(\n agentId: string,\n record: AgentRecord | undefined,\n config: QuorumValidationConfig\n ): EligibilityResult;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Default quorum thresholds by algorithm type.\n * Used for reference when config.threshold is not specified.\n */\nexport const DEFAULT_QUORUM_THRESHOLDS: Readonly<\n Record<ConsensusAlgorithm | 'weighted_byzantine', number>\n> = {\n simple_majority: 0.5,\n supermajority: SUPERMAJORITY_THRESHOLD,\n unanimous: 1.0,\n proof_of_learning: 0.5,\n opinion_wise: 0.5,\n higher_order: 0.5,\n // Byzantine fault tolerance also requires 2/3 — the same supermajority.\n weighted_byzantine: SUPERMAJORITY_THRESHOLD,\n};\n\nconst DEFAULT_MIN_TRUST = 0.3;\nconst DEFAULT_MIN_WEIGHT = 0.1;\n\n/**\n * Unified quorum validator implementation.\n */\nexport class QuorumValidator implements IQuorumValidator {\n private readonly logger: ILogger;\n\n constructor(logger?: ILogger) {\n this.logger = logger ?? createLogger({ component: 'QuorumValidator' });\n }\n\n validateQuorum(input: QuorumValidationInput): QuorumValidationResult {\n const { votes, config } = input;\n\n // Validate input\n if (votes.size === 0) {\n return { status: 'invalid', error: 'No votes provided' };\n }\n\n // Calculate breakdown\n const breakdown = this.getQuorumBreakdown(input);\n\n // Check if quorum reached\n if (!breakdown.quorumReached) {\n return this.buildNotReachedResult(breakdown, config);\n }\n\n // Determine decision\n return this.buildReachedResult(breakdown);\n }\n\n getQuorumBreakdown(input: QuorumValidationInput): QuorumBreakdown {\n const { votes, agentWeights, config, agentRecords, requiredParticipants } = input;\n\n // Count votes\n const voteCounts = this.countVotes(votes);\n const eligibleAgents = this.getEligibleAgents(votes, agentRecords, config);\n\n // Calculate weights if applicable\n const { totalWeight, weightedCounts } = this.calculateWeights(\n votes,\n agentWeights,\n agentRecords,\n config\n );\n\n // Calculate quorum based on algorithm\n const { threshold, actualQuorum, quorumReached, reasoning } = this.calculateQuorumStatus(\n voteCounts,\n weightedCounts,\n totalWeight,\n config,\n requiredParticipants ?? votes.size\n );\n\n return {\n totalVotes: votes.size,\n voteCounts,\n totalWeight,\n weightedCounts,\n threshold,\n actualQuorum,\n quorumReached,\n eligibleAgents,\n reasoning,\n };\n }\n\n isAgentEligible(\n agentId: string,\n record: AgentRecord | undefined,\n config: QuorumValidationConfig\n ): EligibilityResult {\n if (record === undefined) {\n return { eligible: true, weight: 1.0 }; // Default eligibility\n }\n\n // Check Byzantine flags\n if (config.enableByzantineDetection === true && (record.byzantineFlags ?? 0) > 0) {\n this.logger.debug('Agent flagged as Byzantine', { agentId, flags: record.byzantineFlags });\n return { eligible: false, reason: 'byzantine_flagged', weight: record.weight };\n }\n\n // Check trust score\n if (record.trustScore < DEFAULT_MIN_TRUST) {\n this.logger.debug('Agent trust score below threshold', {\n agentId,\n trustScore: record.trustScore,\n });\n return { eligible: false, reason: 'low_trust', weight: record.weight };\n }\n\n // Check weight\n if (record.weight < DEFAULT_MIN_WEIGHT) {\n this.logger.debug('Agent weight below threshold', { agentId, weight: record.weight });\n return { eligible: false, reason: 'insufficient_weight', weight: record.weight };\n }\n\n return { eligible: true, weight: record.weight };\n }\n\n private countVotes(votes: ReadonlyMap<string, Vote>): VoteCounts {\n let approve = 0;\n let reject = 0;\n let abstain = 0;\n\n for (const vote of votes.values()) {\n switch (vote.decision) {\n case 'approve':\n approve++;\n break;\n case 'reject':\n reject++;\n break;\n case 'abstain':\n abstain++;\n break;\n }\n }\n\n return { approve, reject, abstain, total: votes.size };\n }\n\n private getEligibleAgents(\n votes: ReadonlyMap<string, Vote>,\n agentRecords: ReadonlyMap<string, AgentRecord> | undefined,\n config: QuorumValidationConfig\n ): readonly string[] {\n const eligible: string[] = [];\n\n for (const agentId of votes.keys()) {\n const record = agentRecords?.get(agentId);\n const result = this.isAgentEligible(agentId, record, config);\n if (result.eligible) {\n eligible.push(agentId);\n }\n }\n\n return eligible;\n }\n\n private calculateWeights(\n votes: ReadonlyMap<string, Vote>,\n agentWeights: ReadonlyMap<string, number> | undefined,\n agentRecords: ReadonlyMap<string, AgentRecord> | undefined,\n config: QuorumValidationConfig\n ): { totalWeight: number | undefined; weightedCounts: WeightedVoteCounts | undefined } {\n // Skip weight calculation for simple algorithms\n if (config.algorithm === 'simple_majority' || config.algorithm === 'unanimous') {\n return { totalWeight: undefined, weightedCounts: undefined };\n }\n\n const counts = { totalWeight: 0, approve: 0, reject: 0, abstain: 0 };\n\n for (const [agentId, vote] of votes.entries()) {\n const weight = this.getVoteWeight(agentId, vote, agentWeights, agentRecords, config);\n counts.totalWeight += weight;\n this.addWeightToDecision(counts, vote.decision, weight);\n }\n\n return {\n totalWeight: counts.totalWeight,\n weightedCounts: {\n approve: counts.approve,\n reject: counts.reject,\n abstain: counts.abstain,\n totalWeight: counts.totalWeight,\n },\n };\n }\n\n private getVoteWeight(\n agentId: string,\n vote: Vote,\n agentWeights: ReadonlyMap<string, number> | undefined,\n agentRecords: ReadonlyMap<string, AgentRecord> | undefined,\n config: QuorumValidationConfig\n ): number {\n let weight = agentWeights?.get(agentId) ?? agentRecords?.get(agentId)?.weight ?? 1.0;\n if (config.confidenceMultiplier === true) {\n weight *= vote.confidence;\n }\n return weight;\n }\n\n private addWeightToDecision(\n counts: { approve: number; reject: number; abstain: number },\n decision: 'approve' | 'reject' | 'abstain',\n weight: number\n ): void {\n counts[decision] += weight;\n }\n\n private calculateQuorumStatus(\n voteCounts: VoteCounts,\n weightedCounts: WeightedVoteCounts | undefined,\n totalWeight: number | undefined,\n config: QuorumValidationConfig,\n requiredParticipants: number\n ): { threshold: number; actualQuorum: number; quorumReached: boolean; reasoning: string } {\n const threshold = config.threshold;\n\n // For weighted algorithms, use weighted counts\n if (weightedCounts !== undefined && totalWeight !== undefined && totalWeight > 0) {\n return this.calculateWeightedQuorum(weightedCounts, totalWeight, threshold);\n }\n\n // For simple algorithms, use vote counts\n return this.calculateSimpleQuorum(voteCounts, requiredParticipants, threshold, config);\n }\n\n private calculateWeightedQuorum(\n weightedCounts: WeightedVoteCounts,\n totalWeight: number,\n threshold: number\n ): { threshold: number; actualQuorum: number; quorumReached: boolean; reasoning: string } {\n const quorumReached = totalWeight >= threshold;\n const approveRatio = weightedCounts.approve / totalWeight;\n const rejectRatio = weightedCounts.reject / totalWeight;\n\n const reasoning = this.buildWeightedReasoning(\n quorumReached,\n totalWeight,\n threshold,\n approveRatio,\n rejectRatio\n );\n\n return { threshold, actualQuorum: totalWeight, quorumReached, reasoning };\n }\n\n private buildWeightedReasoning(\n quorumReached: boolean,\n totalWeight: number,\n threshold: number,\n approveRatio: number,\n rejectRatio: number\n ): string {\n if (!quorumReached) {\n return `Weighted quorum not reached: ${totalWeight.toFixed(2)} < ${String(threshold)}`;\n }\n if (approveRatio > rejectRatio) {\n return `Approval wins with weighted ratio ${formatPercentage(approveRatio, 1)}`;\n }\n if (rejectRatio > approveRatio) {\n return `Rejection wins with weighted ratio ${formatPercentage(rejectRatio, 1)}`;\n }\n return `No clear winner: approve=${formatPercentage(approveRatio, 1)}, reject=${formatPercentage(rejectRatio, 1)}`;\n }\n\n private calculateSimpleQuorum(\n voteCounts: VoteCounts,\n requiredParticipants: number,\n threshold: number,\n config: QuorumValidationConfig\n ): { threshold: number; actualQuorum: number; quorumReached: boolean; reasoning: string } {\n const activeVotes =\n config.includeAbstentions === true\n ? voteCounts.total\n : voteCounts.approve + voteCounts.reject;\n\n const total = requiredParticipants > 0 ? requiredParticipants : activeVotes;\n const approveRatio = total > 0 ? voteCounts.approve / total : 0;\n const rejectRatio = total > 0 ? voteCounts.reject / total : 0;\n\n const hasMinVoters = activeVotes >= config.minVoters;\n const quorumReached = hasMinVoters && (approveRatio >= threshold || rejectRatio >= threshold);\n\n const reasoning = this.buildSimpleReasoning({\n hasMinVoters,\n activeVotes,\n minVoters: config.minVoters,\n approveRatio,\n rejectRatio,\n threshold,\n });\n\n return {\n threshold,\n actualQuorum: Math.max(approveRatio, rejectRatio),\n quorumReached,\n reasoning,\n };\n }\n\n private buildSimpleReasoning(params: {\n hasMinVoters: boolean;\n activeVotes: number;\n minVoters: number;\n approveRatio: number;\n rejectRatio: number;\n threshold: number;\n }): string {\n const { hasMinVoters, activeVotes, minVoters, approveRatio, rejectRatio, threshold } = params;\n if (!hasMinVoters) {\n return `Insufficient voters: ${String(activeVotes)} < ${String(minVoters)}`;\n }\n if (approveRatio >= threshold) {\n return `Approval reaches threshold: ${formatPercentage(approveRatio, 1)} >= ${formatPercentage(threshold, 1)}`;\n }\n if (rejectRatio >= threshold) {\n return `Rejection reaches threshold: ${formatPercentage(rejectRatio, 1)} >= ${formatPercentage(threshold, 1)}`;\n }\n return `No decision reached threshold: approve=${formatPercentage(approveRatio, 1)}, reject=${formatPercentage(rejectRatio, 1)}`;\n }\n\n private buildNotReachedResult(\n breakdown: QuorumBreakdown,\n config: QuorumValidationConfig\n ): QuorumValidationResult {\n const { voteCounts, weightedCounts, threshold } = breakdown;\n\n if (voteCounts.total < config.minVoters) {\n return {\n status: 'not_reached',\n reason: 'insufficient_votes',\n details: `Only ${String(voteCounts.total)} votes, need ${String(config.minVoters)}`,\n };\n }\n\n if (weightedCounts !== undefined && weightedCounts.totalWeight < threshold) {\n return {\n status: 'not_reached',\n reason: 'insufficient_weight',\n details: `Weight ${weightedCounts.totalWeight.toFixed(2)} < threshold ${String(threshold)}`,\n };\n }\n\n return {\n status: 'not_reached',\n reason: 'no_consensus',\n details: breakdown.reasoning,\n };\n }\n\n private buildReachedResult(breakdown: QuorumBreakdown): QuorumValidationResult {\n const { voteCounts, weightedCounts } = breakdown;\n\n // Determine winning decision\n const approves = weightedCounts?.approve ?? voteCounts.approve;\n const rejects = weightedCounts?.reject ?? voteCounts.reject;\n const total = weightedCounts?.totalWeight ?? voteCounts.total;\n\n const decision: 'approve' | 'reject' = approves >= rejects ? 'approve' : 'reject';\n const confidence = total > 0 ? Math.abs(approves - rejects) / total : 0;\n\n return {\n status: 'reached',\n decision,\n confidence,\n reasoning: breakdown.reasoning,\n };\n }\n}\n\n/**\n * Creates a quorum validator instance.\n */\nexport function createQuorumValidator(logger?: ILogger): IQuorumValidator {\n return new QuorumValidator(logger);\n}\n","/**\n * Helper functions for the multi-round voting protocol.\n *\n * @module consensus/voting-protocol-helpers\n * (Source: Issue #100, arXiv:2512.21352)\n */\n\nimport type {\n VotingSession,\n VotingRound,\n VotingRoundPhase,\n VotingProtocolConfig,\n VotingProtocolResult,\n AgentFinding,\n Vote,\n ConsolidatedFinding,\n RoundSummary,\n SycophancyReport,\n SycophancyIndicator,\n} from './types.js';\nimport { createQuorumValidator, type QuorumValidationConfig } from './quorum-validator.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\n\n/**\n * Generate a unique session ID.\n */\nexport function generateSessionId(): string {\n const time = getTimeProvider();\n const random = getRandomProvider();\n return `session_${String(time.now())}_${random.randomString(7)}`;\n}\n\n/**\n * Generate a unique finding ID.\n */\nexport function generateFindingId(): string {\n const time = getTimeProvider();\n const random = getRandomProvider();\n return `finding_${String(time.now())}_${random.randomString(7)}`;\n}\n\n/**\n * Generate a unique round ID.\n */\nexport function generateRoundId(): string {\n const time = getTimeProvider();\n const random = getRandomProvider();\n return `round_${String(time.now())}_${random.randomString(7)}`;\n}\n\n/**\n * Create a new voting round.\n */\nexport function createRound(phase: VotingRoundPhase, roundNumber: number): VotingRound {\n const time = getTimeProvider();\n return {\n id: generateRoundId(),\n phase,\n status: 'in_progress',\n findings: new Map(),\n findingVotes: new Map(),\n finalVotes: new Map(),\n startedAt: time.nowIso(),\n roundNumber,\n };\n}\n\n/**\n * Find the most common element in an array.\n */\nexport function mostCommon<T>(items: T[]): T | undefined {\n if (items.length === 0) return undefined;\n\n const counts = new Map<T, number>();\n items.forEach((item) => {\n counts.set(item, (counts.get(item) ?? 0) + 1);\n });\n\n let maxCount = 0;\n let result: T | undefined;\n counts.forEach((count, item) => {\n if (count > maxCount) {\n maxCount = count;\n result = item;\n }\n });\n\n return result;\n}\n\n/**\n * Calculate agreement score from votes.\n */\nexport function calculateAgreementScore(votes: Vote[]): number {\n if (votes.length < 2) return 1;\n\n const decisions = votes.map((v) => v.decision);\n const mostCommonDecision = mostCommon(decisions);\n const agreementCount = decisions.filter((d) => d === mostCommonDecision).length;\n\n return agreementCount / votes.length;\n}\n\n/**\n * Determine outcome from final votes using unified QuorumValidator.\n * Per ADR-0003, this delegates to the consolidated quorum logic.\n */\nexport function determineOutcome(\n votes: Vote[],\n config: VotingProtocolConfig\n): VotingProtocolResult['outcome'] {\n if (votes.length === 0) return 'no_consensus';\n\n // Convert array to Map for QuorumValidator\n const voteMap = new Map<string, Vote>();\n votes.forEach((vote, index) => {\n voteMap.set(`voter_${String(index)}`, vote);\n });\n\n // Create quorum config from voting protocol config\n const quorumConfig: QuorumValidationConfig = {\n algorithm: 'simple_majority',\n threshold: config.agreementThreshold,\n minVoters: 2, // Minimum for valid consensus\n };\n\n // Use unified QuorumValidator\n const validator = createQuorumValidator();\n const result = validator.validateQuorum({\n votes: voteMap,\n config: quorumConfig,\n });\n\n // Map QuorumValidationResult to VotingProtocolResult outcome\n if (result.status === 'reached') {\n return result.decision === 'approve' ? 'approved' : 'rejected';\n }\n\n // Check for mixed votes (needs revision)\n const approvals = votes.filter((v) => v.decision === 'approve').length;\n const rejections = votes.filter((v) => v.decision === 'reject').length;\n if (approvals > 0 && rejections > 0) return 'needs_revision';\n\n return 'no_consensus';\n}\n\n/**\n * Consolidate findings from deliberation round.\n */\nexport function consolidateFindings(session: VotingSession): ConsolidatedFinding[] {\n const deliberationRound = session.rounds[1];\n if (!deliberationRound) return [];\n\n const consolidated: ConsolidatedFinding[] = [];\n\n deliberationRound.findings.forEach((finding, findingId) => {\n const votes = deliberationRound.findingVotes.get(findingId) ?? [];\n const agreeVotes = votes.filter((v) => v.agree);\n const agreementRatio = votes.length > 0 ? agreeVotes.length / votes.length : 0;\n\n // Only include findings with some agreement\n if (agreementRatio >= 0.5) {\n // Determine final severity (use most common amended severity or original)\n const severityVotes = agreeVotes\n .filter((v) => v.amendedSeverity)\n .map((v) => v.amendedSeverity);\n const finalSeverity =\n severityVotes.length > 0\n ? (mostCommon(severityVotes) ?? finding.severity)\n : finding.severity;\n\n const consolidatedFinding: ConsolidatedFinding = {\n id: findingId,\n category: finding.category,\n severity: finalSeverity,\n description: finding.description,\n supportingAgents: agreeVotes.map((v) => v.agentId),\n agreementRatio,\n originalFindings: [finding],\n };\n if (finding.location !== undefined) {\n consolidatedFinding.location = finding.location;\n }\n if (finding.suggestion !== undefined) {\n consolidatedFinding.suggestion = finding.suggestion;\n }\n consolidated.push(consolidatedFinding);\n }\n });\n\n // Sort by severity and agreement\n return consolidated.sort((a, b) => {\n const severityOrder = { critical: 0, major: 1, minor: 2, suggestion: 3 };\n const sevDiff = severityOrder[a.severity] - severityOrder[b.severity];\n if (sevDiff !== 0) return sevDiff;\n return b.agreementRatio - a.agreementRatio;\n });\n}\n\n/**\n * Build round summaries from session.\n */\nexport function buildRoundSummaries(session: VotingSession): RoundSummary[] {\n const time = getTimeProvider();\n return session.rounds.map((round, index) => {\n const startTime = new Date(round.startedAt).getTime();\n const endTime =\n round.completedAt !== undefined ? new Date(round.completedAt).getTime() : time.now();\n\n let votesCount = 0;\n let agreementScore = 0;\n\n if (round.phase === 'deliberation') {\n // Count finding votes\n round.findingVotes.forEach((votes) => {\n votesCount += votes.length;\n const agreeCount = votes.filter((v) => v.agree).length;\n agreementScore += votes.length > 0 ? agreeCount / votes.length : 0;\n });\n const findingsCount = round.findingVotes.size;\n if (findingsCount > 0) {\n agreementScore /= findingsCount;\n }\n } else if (round.phase === 'consensus') {\n // Count final votes\n votesCount = round.finalVotes.size;\n const votes = Array.from(round.finalVotes.values());\n agreementScore = calculateAgreementScore(votes);\n }\n\n return {\n roundNumber: index + 1,\n phase: round.phase,\n findingsCount: round.findings.size,\n votesCount,\n agreementScore,\n durationMs: endTime - startTime,\n };\n });\n}\n\n// ============================================================================\n// Sycophancy Detection\n// ============================================================================\n\n/**\n * Check for premature consensus pattern.\n */\nexport function checkPrematureConsensus(session: VotingSession): SycophancyIndicator | null {\n const analysisRound = session.rounds[0];\n if (!analysisRound) return null;\n\n const agentFindings = new Map<string, AgentFinding[]>();\n analysisRound.findings.forEach((finding) => {\n const existing = agentFindings.get(finding.agentId) ?? [];\n existing.push(finding);\n agentFindings.set(finding.agentId, existing);\n });\n\n const allConfidences: number[] = [];\n analysisRound.findings.forEach((finding) => {\n allConfidences.push(finding.confidence);\n });\n\n const avgConfidence =\n allConfidences.length > 0\n ? allConfidences.reduce((a, b) => a + b, 0) / allConfidences.length\n : 0;\n\n if (avgConfidence > 0.95 && agentFindings.size >= 2) {\n return {\n type: 'premature_consensus',\n description: 'All agents showing unusually high confidence',\n severity: 'medium',\n agents: Array.from(agentFindings.keys()),\n };\n }\n\n return null;\n}\n\n/**\n * Check for opinion convergence pattern.\n */\nexport function checkOpinionConvergence(session: VotingSession): SycophancyIndicator | null {\n const deliberationRound = session.rounds[1];\n if (!deliberationRound) return null;\n\n let totalVotes = 0;\n let agreeVotes = 0;\n\n deliberationRound.findingVotes.forEach((votes) => {\n totalVotes += votes.length;\n agreeVotes += votes.filter((v) => v.agree).length;\n });\n\n const agreeRatio = totalVotes > 0 ? agreeVotes / totalVotes : 0;\n\n if (agreeRatio > session.config.sycophancyThreshold && totalVotes > 3) {\n const affectedAgents: string[] = [];\n deliberationRound.findingVotes.forEach((votes) => {\n votes.forEach((v) => {\n if (v.agree && !affectedAgents.includes(v.agentId)) {\n affectedAgents.push(v.agentId);\n }\n });\n });\n\n return {\n type: 'opinion_convergence',\n description: `${String(Math.round(agreeRatio * 100))}% agreement rate suggests possible opinion convergence`,\n severity: 'high',\n agents: affectedAgents,\n };\n }\n\n return null;\n}\n\n/**\n * Check for confidence inflation pattern.\n */\nexport function checkConfidenceInflation(session: VotingSession): SycophancyIndicator | null {\n const consensusRound = session.rounds[2];\n if (!consensusRound) return null;\n\n const votes = Array.from(consensusRound.finalVotes.values());\n if (votes.length < 2) return null;\n\n const confidences = votes.map((v) => v.confidence);\n const avgConfidence = confidences.reduce((a, b) => a + b, 0) / confidences.length;\n const allHigh = confidences.every((c) => c > 0.9);\n\n if (allHigh && avgConfidence > 0.95) {\n return {\n type: 'confidence_inflation',\n description: 'All agents reporting very high confidence suggests possible sycophancy',\n severity: 'medium',\n agents: Array.from(consensusRound.finalVotes.keys()),\n };\n }\n\n return null;\n}\n\n/**\n * Run all sycophancy detection checks.\n */\nexport function detectSycophancyPatterns(session: VotingSession): SycophancyReport {\n const indicators: SycophancyIndicator[] = [];\n const affectedAgents: string[] = [];\n\n const prematureConsensus = checkPrematureConsensus(session);\n if (prematureConsensus) {\n indicators.push(prematureConsensus);\n affectedAgents.push(...prematureConsensus.agents);\n }\n\n const opinionConvergence = checkOpinionConvergence(session);\n if (opinionConvergence) {\n indicators.push(opinionConvergence);\n affectedAgents.push(...opinionConvergence.agents);\n }\n\n const confidenceInflation = checkConfidenceInflation(session);\n if (confidenceInflation) {\n indicators.push(confidenceInflation);\n affectedAgents.push(...confidenceInflation.agents);\n }\n\n const detected = indicators.length > 0;\n const confidenceScore = Math.min(1, indicators.length * 0.3);\n const uniqueAffected = [...new Set(affectedAgents)];\n\n return {\n detected,\n confidenceScore,\n indicators,\n affectedAgents: uniqueAffected,\n recommendation: detected\n ? 'Consider requesting independent re-analysis or adding more diverse agents'\n : 'No sycophancy detected',\n };\n}\n","/**\n * Multi-Round Voting Protocol Implementation\n *\n * Implements a structured 3-round voting protocol for multi-agent code review\n * based on research showing 91.7-100% success rates vs 78% single-agent baseline.\n *\n * @module consensus/voting-protocol\n * (Source: Issue #100, arXiv:2512.21352 - Multi-Agent Committees)\n * (Source: arXiv:2509.23055 - Sycophancy Prevention)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type { ILogger } from '../core/index.js';\nimport type {\n IVotingProtocol,\n VotingSession,\n VotingRound,\n VotingProtocolConfig,\n VotingProtocolResult,\n AgentFinding,\n FindingVote,\n Vote,\n SycophancyReport,\n} from './types.js';\nimport {\n AgentFindingSchema,\n FindingVoteSchema,\n VoteSchema,\n DEFAULT_VOTING_PROTOCOL_CONFIG,\n} from './types.js';\nimport {\n generateSessionId,\n generateFindingId,\n createRound,\n consolidateFindings,\n buildRoundSummaries,\n determineOutcome,\n calculateAgreementScore,\n detectSycophancyPatterns,\n} from './voting-protocol-helpers.js';\n\nconst logger: ILogger = createLogger({ component: 'voting-protocol' });\n\n/**\n * Multi-round voting protocol for code review.\n */\nexport class VotingProtocol implements IVotingProtocol {\n private readonly sessions: Map<string, VotingSession> = new Map();\n private readonly logger: ILogger;\n\n constructor(customLogger?: ILogger) {\n this.logger = customLogger ?? logger;\n }\n\n /**\n * Create a new voting session with a committee.\n */\n createSession(\n topic: string,\n committee: string[],\n config?: Partial<VotingProtocolConfig>\n ): VotingSession {\n const sessionConfig = { ...DEFAULT_VOTING_PROTOCOL_CONFIG, ...config };\n\n if (committee.length < 2) {\n throw new Error('Committee must have at least 2 members');\n }\n\n if (committee.length > sessionConfig.committeeSize) {\n throw new Error(`Committee size exceeds maximum (${String(sessionConfig.committeeSize)})`);\n }\n\n const session: VotingSession = {\n id: generateSessionId(),\n topic,\n committee,\n rounds: [],\n currentRound: 0,\n config: sessionConfig,\n status: 'active',\n createdAt: getTimeProvider().nowIso(),\n };\n\n this.sessions.set(session.id, session);\n this.logger.info('Voting session created', {\n sessionId: session.id,\n topic,\n committeeSize: committee.length,\n });\n\n return session;\n }\n\n /**\n * Start the analysis round (Round 1).\n */\n startAnalysisRound(sessionId: string): Promise<VotingRound> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n if (session.currentRound !== 0) {\n return Promise.reject(new Error('Analysis round can only be started as Round 1'));\n }\n\n const round = createRound('analysis', 1);\n session.rounds.push(round);\n session.currentRound = 1;\n\n this.logger.info('Analysis round started', { sessionId, roundId: round.id });\n return Promise.resolve(round);\n }\n\n /**\n * Submit findings from an agent during analysis.\n */\n submitFindings(sessionId: string, agentId: string, findings: AgentFinding[]): Promise<void> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n const currentRound = this.getCurrentRound(session);\n if (currentRound.phase !== 'analysis') {\n return Promise.reject(new Error('Findings can only be submitted during analysis round'));\n }\n\n if (!session.committee.includes(agentId)) {\n return Promise.reject(new Error(`Agent ${agentId} is not a committee member`));\n }\n\n for (const finding of findings) {\n const validation = AgentFindingSchema.safeParse(finding);\n if (!validation.success) {\n return Promise.reject(new Error(`Invalid finding: ${validation.error.message}`));\n }\n\n const findingId = generateFindingId();\n const timestampedFinding = {\n ...validation.data,\n agentId,\n timestamp: getTimeProvider().nowIso(),\n };\n currentRound.findings.set(findingId, timestampedFinding);\n }\n\n this.logger.debug('Findings submitted', { sessionId, agentId, findingsCount: findings.length });\n return Promise.resolve();\n }\n\n /**\n * Start the deliberation round (Round 2).\n */\n startDeliberationRound(sessionId: string): Promise<VotingRound> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n if (session.currentRound !== 1) {\n return Promise.reject(new Error('Deliberation round can only be started after analysis'));\n }\n\n const analysisRound = session.rounds[0];\n if (analysisRound) {\n analysisRound.status = 'completed';\n analysisRound.completedAt = getTimeProvider().nowIso();\n }\n\n if (session.config.enableAntiSycophancy) {\n const report = this.detectSycophancy(sessionId);\n if (report.detected) {\n this.logger.warn('Sycophancy detected before deliberation', {\n sessionId,\n indicators: report.indicators.length,\n });\n }\n }\n\n const round = createRound('deliberation', 2);\n if (analysisRound) {\n analysisRound.findings.forEach((finding, id) => {\n round.findings.set(id, finding);\n round.findingVotes.set(id, []);\n });\n }\n\n session.rounds.push(round);\n session.currentRound = 2;\n\n this.logger.info('Deliberation round started', {\n sessionId,\n roundId: round.id,\n findingsCount: round.findings.size,\n });\n return Promise.resolve(round);\n }\n\n /**\n * Vote on findings during deliberation.\n */\n voteOnFinding(sessionId: string, vote: FindingVote): Promise<void> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n const currentRound = this.getCurrentRound(session);\n if (currentRound.phase !== 'deliberation') {\n return Promise.reject(new Error('Finding votes can only be submitted during deliberation'));\n }\n\n const validation = FindingVoteSchema.safeParse(vote);\n if (!validation.success) {\n return Promise.reject(new Error(`Invalid vote: ${validation.error.message}`));\n }\n\n if (!session.committee.includes(vote.agentId)) {\n return Promise.reject(new Error(`Agent ${vote.agentId} is not a committee member`));\n }\n\n if (!currentRound.findings.has(vote.findingId)) {\n return Promise.reject(new Error(`Finding ${vote.findingId} not found`));\n }\n\n const existingVotes = currentRound.findingVotes.get(vote.findingId) ?? [];\n const filtered = existingVotes.filter((v) => v.agentId !== vote.agentId);\n filtered.push(validation.data);\n currentRound.findingVotes.set(vote.findingId, filtered);\n\n this.logger.debug('Finding vote recorded', {\n sessionId,\n agentId: vote.agentId,\n findingId: vote.findingId,\n agree: vote.agree,\n });\n return Promise.resolve();\n }\n\n /**\n * Start the consensus round (Round 3).\n */\n startConsensusRound(sessionId: string): Promise<VotingRound> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n if (session.currentRound !== 2) {\n return Promise.reject(new Error('Consensus round can only be started after deliberation'));\n }\n\n const deliberationRound = session.rounds[1];\n if (deliberationRound) {\n deliberationRound.status = 'completed';\n deliberationRound.completedAt = getTimeProvider().nowIso();\n }\n\n const round = createRound('consensus', 3);\n session.rounds.push(round);\n session.currentRound = 3;\n\n this.logger.info('Consensus round started', { sessionId, roundId: round.id });\n return Promise.resolve(round);\n }\n\n /**\n * Submit final vote during consensus.\n */\n submitFinalVote(sessionId: string, agentId: string, vote: Vote): Promise<void> {\n const session = this.getSessionOrThrow(sessionId);\n this.validateSessionActive(session);\n\n const currentRound = this.getCurrentRound(session);\n if (currentRound.phase !== 'consensus') {\n return Promise.reject(new Error('Final votes can only be submitted during consensus'));\n }\n\n const validation = VoteSchema.safeParse(vote);\n if (!validation.success) {\n return Promise.reject(new Error(`Invalid vote: ${validation.error.message}`));\n }\n\n if (!session.committee.includes(agentId)) {\n return Promise.reject(new Error(`Agent ${agentId} is not a committee member`));\n }\n\n currentRound.finalVotes.set(agentId, {\n ...validation.data,\n timestamp: getTimeProvider().nowIso(),\n });\n\n this.logger.debug('Final vote recorded', {\n sessionId,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n });\n return Promise.resolve();\n }\n\n /**\n * Get the final result.\n */\n getResult(sessionId: string): Promise<VotingProtocolResult | null> {\n const session = this.sessions.get(sessionId);\n if (!session) return Promise.resolve(null);\n\n if (session.status === 'completed' && session.finalResult) {\n return Promise.resolve(session.finalResult);\n }\n\n if (session.currentRound < 3) return Promise.resolve(null);\n\n const consensusRound = session.rounds[2];\n if (!consensusRound) return Promise.resolve(null);\n\n const allVoted = session.committee.every((agentId) => consensusRound.finalVotes.has(agentId));\n if (!allVoted) return Promise.resolve(null);\n\n const result = this.buildFinalResult(session);\n session.finalResult = result;\n session.status = 'completed';\n session.completedAt = getTimeProvider().nowIso();\n\n consensusRound.status = 'completed';\n consensusRound.completedAt = getTimeProvider().nowIso();\n\n this.logger.info('Voting session completed', {\n sessionId,\n outcome: result.outcome,\n agreementScore: result.agreementScore,\n consolidatedFindings: result.consolidatedFindings.length,\n });\n\n return Promise.resolve(result);\n }\n\n /**\n * Detect sycophancy patterns.\n */\n detectSycophancy(sessionId: string): SycophancyReport {\n const session = this.getSessionOrThrow(sessionId);\n return detectSycophancyPatterns(session);\n }\n\n /**\n * Get the current session state.\n */\n getSession(sessionId: string): VotingSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n private getSessionOrThrow(sessionId: string): VotingSession {\n const session = this.sessions.get(sessionId);\n if (!session) {\n throw new Error(`Session ${sessionId} not found`);\n }\n return session;\n }\n\n private validateSessionActive(session: VotingSession): void {\n if (session.status !== 'active') {\n throw new Error(`Session ${session.id} is ${session.status}`);\n }\n }\n\n private getCurrentRound(session: VotingSession): VotingRound {\n const round = session.rounds[session.currentRound - 1];\n if (!round) {\n throw new Error(`No round ${String(session.currentRound)} found`);\n }\n return round;\n }\n\n private buildFinalResult(session: VotingSession): VotingProtocolResult {\n const startTime = new Date(session.createdAt).getTime();\n const endTime = getTimeProvider().now();\n\n const consolidatedFindingsList = consolidateFindings(session);\n const roundSummaries = buildRoundSummaries(session);\n\n const consensusRound = session.rounds[2];\n const finalVotes = consensusRound ? Array.from(consensusRound.finalVotes.values()) : [];\n const outcome = determineOutcome(finalVotes, session.config);\n const agreementScore = calculateAgreementScore(finalVotes);\n const sycophancyReport = detectSycophancyPatterns(session);\n\n return {\n sessionId: session.id,\n topic: session.topic,\n outcome,\n consolidatedFindings: consolidatedFindingsList,\n roundSummaries,\n agreementScore,\n sycophancyDetected: sycophancyReport.detected,\n totalDurationMs: endTime - startTime,\n participatingAgents: session.committee,\n };\n }\n}\n\n/**\n * Create a voting protocol instance.\n */\nexport function createVotingProtocol(customLogger?: ILogger): VotingProtocol {\n return new VotingProtocol(customLogger);\n}\n","/**\n * Byzantine Detection EventBus Integration Helpers\n * (Source: Issue #218, Sprint #228)\n *\n * Provides helper functions for emitting Byzantine fault detection events.\n * Used by CP-WBFT weighted voting to report Byzantine behavior patterns.\n *\n * @module agents/collaboration/byzantine-events\n */\n\nimport type {\n IEventBus,\n ByzantineWeightUpdatedEvent,\n ByzantinePatternDetectedEvent,\n ByzantineAgentFlaggedEvent,\n ByzantineCollusionSuspectedEvent,\n} from './event-bus-types.js';\nimport { createEvent } from './event-bus.js';\n\n// =============================================================================\n// Weight Update Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.weight_updated event. */\nexport interface WeightUpdatedParams {\n readonly agentId: string;\n readonly previousWeight: number;\n readonly newWeight: number;\n readonly reason: 'performance_update' | 'flag_penalty' | 'recalibration';\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.weight_updated event when an agent's weight changes. */\nexport function emitWeightUpdated(eventBus: IEventBus, params: WeightUpdatedParams): void {\n const event = createEvent<ByzantineWeightUpdatedEvent>(\n 'byzantine.weight_updated',\n {\n agentId: params.agentId,\n previousWeight: params.previousWeight,\n newWeight: params.newWeight,\n reason: params.reason,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n\n// =============================================================================\n// Pattern Detection Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.pattern_detected event. */\nexport interface PatternDetectedParams {\n readonly patternType: 'contrarian' | 'collusion';\n readonly agentIds: readonly string[];\n readonly confidence: number;\n readonly details: string;\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.pattern_detected event when Byzantine pattern is detected. */\nexport function emitPatternDetected(eventBus: IEventBus, params: PatternDetectedParams): void {\n const event = createEvent<ByzantinePatternDetectedEvent>(\n 'byzantine.pattern_detected',\n {\n patternType: params.patternType,\n agentIds: params.agentIds,\n confidence: params.confidence,\n details: params.details,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n\n// =============================================================================\n// Agent Flagged Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.agent_flagged event. */\nexport interface AgentFlaggedParams {\n readonly agentId: string;\n readonly reason: string;\n readonly previousWeight: number;\n readonly canVote: boolean;\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.agent_flagged event when an agent is flagged as Byzantine. */\nexport function emitAgentFlagged(eventBus: IEventBus, params: AgentFlaggedParams): void {\n const event = createEvent<ByzantineAgentFlaggedEvent>(\n 'byzantine.agent_flagged',\n {\n agentId: params.agentId,\n reason: params.reason,\n previousWeight: params.previousWeight,\n canVote: params.canVote,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n\n// =============================================================================\n// Collusion Suspected Events\n// =============================================================================\n\n/** Parameters for emitting byzantine.collusion_suspected event. */\nexport interface CollusionSuspectedParams {\n readonly groupAgentIds: readonly string[];\n readonly groupSize: number;\n readonly votingBlock: number;\n readonly threshold: number;\n readonly sessionId?: string | undefined;\n readonly correlationId?: string | undefined;\n}\n\n/** Emits byzantine.collusion_suspected event when collusion pattern is suspected. */\nexport function emitCollusionSuspected(\n eventBus: IEventBus,\n params: CollusionSuspectedParams\n): void {\n const event = createEvent<ByzantineCollusionSuspectedEvent>(\n 'byzantine.collusion_suspected',\n {\n groupAgentIds: params.groupAgentIds,\n groupSize: params.groupSize,\n votingBlock: params.votingBlock,\n threshold: params.threshold,\n },\n {\n ...(params.sessionId !== undefined && { sessionId: params.sessionId }),\n ...(params.correlationId !== undefined && { correlationId: params.correlationId }),\n }\n );\n eventBus.emit(event);\n}\n","/**\n * nexus-agents/consensus - Weighted Byzantine Voting Helpers\n *\n * Pure helper functions extracted from WeightedVoting class.\n * These functions are stateless and operate on parameters only.\n *\n * @module consensus/weighted-voting-helpers\n * (Source: Issue #103, arXiv:2511.10400 - CP-WBFT)\n */\n\nimport { getTimeProvider } from '../core/index.js';\nimport { clamp01 } from '../utils/math-utils.js';\nimport type { WeightedAgentRecord, WeightedConsensusResult, Vote } from './types.js';\nimport type { IEventBus } from '../core/event-bus.js';\n\n/**\n * Mutable agent record for internal tracking.\n * Used internally by WeightedVoting class.\n */\nexport interface MutableAgentRecord {\n agentId: string;\n totalTasks: number;\n successfulTasks: number;\n failedTasks: number;\n partialTasks: number;\n successRate: number;\n weight: number;\n trustScore: number;\n byzantineFlags: number;\n byzantineReasons: string[];\n lastActive: Date;\n createdAt: Date;\n}\n\n/** Options for WeightedVoting constructor. */\nexport interface WeightedVotingOptions {\n /** Configuration for voting thresholds and weights. */\n config?: Partial<import('./types.js').WeightedVotingConfig>;\n /** Optional event bus for Byzantine detection events (Issue #218). */\n eventBus?: IEventBus;\n /** Whether to emit Byzantine detection events (default: true if eventBus provided). */\n emitEvents?: boolean;\n}\n\n/**\n * Check if a vote is a low-confidence contrarian vote.\n * Used for Byzantine pattern detection.\n */\nexport function isLowConfidenceContrarian(vote: Vote, majorityApprove: boolean): boolean {\n const isContrarian = majorityApprove ? vote.decision === 'reject' : vote.decision === 'approve';\n return isContrarian && vote.confidence < 0.3;\n}\n\n/**\n * Compute the majority vote direction based on weighted votes.\n * Returns true if majority approves, false if majority rejects.\n */\nexport function computeMajorityDirection(\n voteArray: ReadonlyArray<readonly [string, Vote]>,\n weights: ReadonlyMap<string, number>\n): boolean {\n let totalApprove = 0;\n let totalReject = 0;\n for (const [agentId, vote] of voteArray) {\n const w = weights.get(agentId) ?? 0;\n if (vote.decision === 'approve') totalApprove += w;\n if (vote.decision === 'reject') totalReject += w;\n }\n return totalApprove > totalReject;\n}\n\n/**\n * Determine consensus decision based on vote tallies.\n */\nexport function determineDecision(\n approval: number,\n rejection: number,\n total: number,\n quorumReached: boolean,\n quorumThreshold: number\n): WeightedConsensusResult['decision'] {\n if (!quorumReached || total === 0) return 'no_consensus';\n const approvalRatio = approval / total;\n const rejectionRatio = rejection / total;\n if (approvalRatio > rejectionRatio && approvalRatio >= quorumThreshold) return 'approve';\n if (rejectionRatio > approvalRatio && rejectionRatio >= quorumThreshold) return 'reject';\n return 'no_consensus';\n}\n\n/**\n * Update derived metrics (success rate, trust score) on a mutable record.\n */\nexport function updateDerivedMetrics(record: MutableAgentRecord): void {\n // Update success rate\n if (record.totalTasks > 0) {\n const weightedSuccess = record.successfulTasks + record.partialTasks * 0.5;\n record.successRate = weightedSuccess / record.totalTasks;\n }\n\n // Update trust score based on weight and Byzantine flags\n const byzantinePenalty = Math.pow(0.7, record.byzantineFlags);\n record.trustScore = Math.min(1, record.weight * byzantinePenalty);\n}\n\n/**\n * Convert a mutable internal record to an immutable public record.\n */\nexport function toImmutableRecord(record: MutableAgentRecord): WeightedAgentRecord {\n return {\n agentId: record.agentId,\n totalTasks: record.totalTasks,\n successfulTasks: record.successfulTasks,\n failedTasks: record.failedTasks,\n partialTasks: record.partialTasks,\n successRate: record.successRate,\n weight: record.weight,\n trustScore: record.trustScore,\n byzantineFlags: record.byzantineFlags,\n lastActive: record.lastActive,\n createdAt: record.createdAt,\n };\n}\n\n/**\n * Create a vote signature for collusion detection.\n * Combines decision and confidence into a unique key.\n */\nexport function createVoteSignature(vote: Vote): string {\n return `${vote.decision}:${vote.confidence.toFixed(2)}`;\n}\n\n/**\n * Group votes by their signature for collusion pattern detection.\n */\nexport function groupVotesBySignature(\n voteArray: ReadonlyArray<readonly [string, Vote]>\n): Map<string, string[]> {\n const signatures = new Map<string, string[]>();\n for (const [agentId, vote] of voteArray) {\n const sig = createVoteSignature(vote);\n const agents = signatures.get(sig) ?? [];\n agents.push(agentId);\n signatures.set(sig, agents);\n }\n return signatures;\n}\n\n/**\n * Create a new mutable agent record with initial values.\n */\nexport function createAgentRecord(agentId: string, initialWeight: number): MutableAgentRecord {\n const now = new Date(getTimeProvider().now());\n return {\n agentId,\n totalTasks: 0,\n successfulTasks: 0,\n failedTasks: 0,\n partialTasks: 0,\n successRate: 0,\n weight: initialWeight,\n trustScore: initialWeight,\n byzantineFlags: 0,\n byzantineReasons: [],\n lastActive: now,\n createdAt: now,\n };\n}\n\n/**\n * Compute global success statistics from all agent records.\n */\nexport function computeGlobalStats(records: Iterable<MutableAgentRecord>): {\n globalSuccessRate: number;\n totalTasks: number;\n} {\n let totalSuccess = 0;\n let totalTasks = 0;\n\n for (const record of records) {\n totalSuccess += record.successfulTasks;\n totalTasks += record.totalTasks;\n }\n\n const globalSuccessRate = totalTasks > 0 ? totalSuccess / totalTasks : 0.5;\n return { globalSuccessRate, totalTasks };\n}\n\n/**\n * Calculate calibrated weight based on relative performance.\n */\nexport function calculateCalibratedWeight(\n record: MutableAgentRecord,\n globalSuccessRate: number,\n initialWeight: number\n): number {\n const relativePerformance = record.successRate / Math.max(0.01, globalSuccessRate);\n const calibratedWeight = clamp01(initialWeight * relativePerformance);\n // Smooth transition (50% old weight, 50% calibrated)\n return (record.weight + calibratedWeight) / 2;\n}\n\n/**\n * Apply weight change based on task outcome.\n */\nexport function applyOutcomeWeight(\n currentWeight: number,\n outcome: import('./types.js').TaskOutcomeStatus,\n decayFactor: number,\n recoveryFactor: number\n): number {\n switch (outcome) {\n case 'success':\n return Math.min(1, currentWeight * recoveryFactor);\n case 'failure':\n return Math.max(0, currentWeight * decayFactor);\n case 'partial':\n return Math.max(0, currentWeight * ((decayFactor + 1) / 2));\n case 'unknown':\n return currentWeight;\n }\n}\n","/**\n * nexus-agents/consensus - Weighted Byzantine Voting Implementation\n *\n * Implements CP-WBFT (arXiv:2511.10400) for weighted Byzantine fault-tolerant voting.\n * Agent votes are weighted by historical reliability with automatic trust calibration.\n *\n * @module consensus/weighted-voting\n * (Source: Issue #103, arXiv:2511.10400 - CP-WBFT)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport { getTimeProvider } from '../core/index.js';\nimport type {\n IWeightedVoting,\n WeightedAgentRecord,\n WeightedConsensusResult,\n WeightedVotingConfig,\n TaskOutcomeStatus,\n Vote,\n} from './types.js';\nimport { DEFAULT_WEIGHTED_VOTING_CONFIG } from './types.js';\nimport type { IEventBus } from '../core/event-bus.js';\nimport {\n emitWeightUpdated,\n emitPatternDetected,\n emitAgentFlagged,\n emitCollusionSuspected,\n} from '../agents/collaboration/byzantine-events.js';\nimport {\n type MutableAgentRecord,\n type WeightedVotingOptions,\n isLowConfidenceContrarian,\n computeMajorityDirection,\n determineDecision,\n updateDerivedMetrics,\n toImmutableRecord,\n groupVotesBySignature,\n createAgentRecord,\n computeGlobalStats,\n calculateCalibratedWeight,\n applyOutcomeWeight,\n} from './weighted-voting-helpers.js';\n\nexport type { WeightedVotingOptions } from './weighted-voting-helpers.js';\n\nconst logger = createLogger({ component: 'weighted-voting' });\n\n/**\n * Weighted Byzantine voting implementation.\n * Implements CP-WBFT pattern for fault-tolerant multi-agent consensus.\n */\nexport class WeightedVoting implements IWeightedVoting {\n private readonly records: Map<string, MutableAgentRecord> = new Map();\n private readonly config: WeightedVotingConfig;\n private readonly eventBus: IEventBus | undefined;\n private readonly emitEvents: boolean;\n\n constructor(options: WeightedVotingOptions = {}) {\n this.config = { ...DEFAULT_WEIGHTED_VOTING_CONFIG, ...options.config };\n this.eventBus = options.eventBus ?? undefined;\n this.emitEvents = options.emitEvents ?? options.eventBus !== undefined;\n logger.info('WeightedVoting initialized', {\n config: this.config,\n eventsEnabled: this.emitEvents,\n });\n }\n\n calculateWeight(agentId: string): number {\n const record = this.records.get(agentId);\n if (record === undefined) return 0;\n return record.weight;\n }\n\n updatePerformance(agentId: string, outcome: TaskOutcomeStatus): void {\n let record = this.records.get(agentId);\n if (record === undefined) {\n this.registerAgent(agentId);\n record = this.records.get(agentId);\n if (record === undefined) return;\n }\n\n const previousWeight = record.weight;\n record.totalTasks += 1;\n record.lastActive = new Date(getTimeProvider().now());\n\n // Update task counts\n if (outcome === 'success') record.successfulTasks += 1;\n else if (outcome === 'failure') record.failedTasks += 1;\n else if (outcome === 'partial') record.partialTasks += 1;\n\n // Apply weight change\n record.weight = applyOutcomeWeight(\n record.weight,\n outcome,\n this.config.weightDecayFactor,\n this.config.weightRecoveryFactor\n );\n updateDerivedMetrics(record);\n this.emitWeightChange(agentId, previousWeight, record.weight, 'performance_update');\n\n logger.debug('Performance updated', {\n agentId,\n outcome,\n newWeight: record.weight,\n successRate: record.successRate,\n });\n }\n\n weightedConsensus(votes: ReadonlyMap<string, Vote>): WeightedConsensusResult {\n const { approval, rejection, total, agents, breakdown } = this.countVotes(votes);\n const byzantineDetected = this.detectByzantinePatterns(votes, breakdown);\n const quorumReached = total >= this.config.quorumThreshold;\n const decision = determineDecision(\n approval,\n rejection,\n total,\n quorumReached,\n this.config.quorumThreshold\n );\n\n const result: WeightedConsensusResult = {\n decision,\n weightedApproval: approval,\n weightedRejection: rejection,\n totalWeight: total,\n quorumReached,\n byzantineDetected,\n participatingAgents: agents,\n weightBreakdown: breakdown,\n };\n\n this.logConsensusResult(result);\n return result;\n }\n\n registerAgent(agentId: string): void {\n if (this.records.has(agentId)) {\n logger.debug('Agent already registered', { agentId });\n return;\n }\n const record = createAgentRecord(agentId, this.config.initialWeight);\n this.records.set(agentId, record);\n logger.info('Agent registered', { agentId, initialWeight: this.config.initialWeight });\n }\n\n getAgentRecord(agentId: string): WeightedAgentRecord | undefined {\n const record = this.records.get(agentId);\n if (record === undefined) return undefined;\n return toImmutableRecord(record);\n }\n\n flagByzantine(agentId: string, reason: string): void {\n const record = this.records.get(agentId);\n if (record === undefined) {\n logger.warn('Cannot flag unregistered agent', { agentId });\n return;\n }\n\n const previousWeight = record.weight;\n record.byzantineFlags += 1;\n record.byzantineReasons.push(reason);\n record.weight = Math.max(0, record.weight * 0.5);\n updateDerivedMetrics(record);\n\n const canStillVote = this.canVote(agentId);\n this.emitAgentFlaggedEvent(agentId, reason, previousWeight, canStillVote);\n this.emitWeightChange(agentId, previousWeight, record.weight, 'flag_penalty');\n\n logger.warn('Agent flagged for Byzantine behavior', {\n agentId,\n reason,\n totalFlags: record.byzantineFlags,\n newWeight: record.weight,\n });\n\n if (record.byzantineFlags >= this.config.byzantineFlagThreshold) {\n this.excludeAgent(record);\n }\n }\n\n getAllRecords(): readonly WeightedAgentRecord[] {\n return Array.from(this.records.values()).map((r) => toImmutableRecord(r));\n }\n\n canVote(agentId: string): boolean {\n const record = this.records.get(agentId);\n if (record === undefined) return false;\n return record.weight >= this.config.minWeight && record.trustScore >= this.config.minTrustScore;\n }\n\n recalibrateWeights(): void {\n const { globalSuccessRate, totalTasks } = computeGlobalStats(this.records.values());\n if (totalTasks === 0) return;\n\n for (const record of this.records.values()) {\n if (record.totalTasks < 3) continue;\n const previousWeight = record.weight;\n record.weight = calculateCalibratedWeight(\n record,\n globalSuccessRate,\n this.config.initialWeight\n );\n updateDerivedMetrics(record);\n this.emitWeightChange(record.agentId, previousWeight, record.weight, 'recalibration');\n }\n\n logger.info('Weights recalibrated', {\n agentCount: this.records.size,\n globalSuccessRate: globalSuccessRate.toFixed(3),\n });\n }\n\n // Private helpers\n\n private countVotes(votes: ReadonlyMap<string, Vote>): {\n approval: number;\n rejection: number;\n total: number;\n agents: string[];\n breakdown: Map<string, number>;\n } {\n let approval = 0;\n let rejection = 0;\n let total = 0;\n const agents: string[] = [];\n const breakdown = new Map<string, number>();\n\n for (const [agentId, vote] of votes) {\n if (!this.canVote(agentId)) {\n logger.warn('Agent cannot vote', { agentId, reason: 'insufficient weight or trust' });\n continue;\n }\n const weight = this.calculateWeight(agentId);\n breakdown.set(agentId, weight);\n agents.push(agentId);\n total += weight;\n const effectiveWeight = weight * vote.confidence;\n if (vote.decision === 'approve') approval += effectiveWeight;\n else if (vote.decision === 'reject') rejection += effectiveWeight;\n }\n return { approval, rejection, total, agents, breakdown };\n }\n\n private logConsensusResult(result: WeightedConsensusResult): void {\n logger.info('Weighted consensus calculated', {\n decision: result.decision,\n approval: result.weightedApproval.toFixed(3),\n rejection: result.weightedRejection.toFixed(3),\n totalWeight: result.totalWeight.toFixed(3),\n quorumReached: result.quorumReached,\n byzantineDetected: result.byzantineDetected,\n });\n }\n\n private emitWeightChange(\n agentId: string,\n prev: number,\n next: number,\n reason: 'performance_update' | 'flag_penalty' | 'recalibration'\n ): void {\n if (this.emitEvents && this.eventBus !== undefined && prev !== next) {\n emitWeightUpdated(this.eventBus, { agentId, previousWeight: prev, newWeight: next, reason });\n }\n }\n\n private emitAgentFlaggedEvent(\n agentId: string,\n reason: string,\n previousWeight: number,\n canVote: boolean\n ): void {\n if (this.emitEvents && this.eventBus !== undefined) {\n emitAgentFlagged(this.eventBus, { agentId, reason, previousWeight, canVote });\n }\n }\n\n private excludeAgent(record: MutableAgentRecord): void {\n const weightBefore = record.weight;\n record.trustScore = 0;\n record.weight = 0;\n this.emitWeightChange(record.agentId, weightBefore, 0, 'flag_penalty');\n logger.warn('Agent excluded from voting due to Byzantine behavior', {\n agentId: record.agentId,\n flags: record.byzantineFlags,\n });\n }\n\n private detectByzantinePatterns(\n votes: ReadonlyMap<string, Vote>,\n weights: Map<string, number>\n ): boolean {\n const voteArray = Array.from(votes.entries());\n if (voteArray.length < 3) return false;\n const majorityApprove = computeMajorityDirection(voteArray, weights);\n if (this.detectContrarianByzantine(voteArray, majorityApprove)) return true;\n return this.detectCollusionPattern(voteArray);\n }\n\n private detectContrarianByzantine(\n voteArray: Array<[string, Vote]>,\n majorityApprove: boolean\n ): boolean {\n const contrarianAgents: string[] = [];\n for (const [agentId, vote] of voteArray) {\n if (!isLowConfidenceContrarian(vote, majorityApprove)) continue;\n const record = this.records.get(agentId);\n if (record !== undefined && record.byzantineFlags >= 2) {\n contrarianAgents.push(agentId);\n }\n }\n if (contrarianAgents.length > 0) {\n this.emitContrarianPattern(contrarianAgents);\n return true;\n }\n return false;\n }\n\n private emitContrarianPattern(agents: string[]): void {\n if (this.emitEvents && this.eventBus !== undefined) {\n emitPatternDetected(this.eventBus, {\n patternType: 'contrarian',\n agentIds: agents,\n confidence: 0.8,\n details: `${String(agents.length)} agent(s) with Byzantine flags voting contrary to majority with low confidence`,\n });\n }\n }\n\n private detectCollusionPattern(voteArray: Array<[string, Vote]>): boolean {\n const voteSignatures = groupVotesBySignature(voteArray);\n const threshold = voteArray.length * 0.6;\n for (const [signature, agents] of voteSignatures.entries()) {\n if (agents.length >= 3 && agents.length > threshold) {\n this.emitCollusionEvents(agents, signature, voteArray.length);\n return true;\n }\n }\n return false;\n }\n\n private emitCollusionEvents(agents: string[], signature: string, totalVotes: number): void {\n if (this.emitEvents && this.eventBus !== undefined) {\n emitPatternDetected(this.eventBus, {\n patternType: 'collusion',\n agentIds: agents,\n confidence: Math.min(0.95, agents.length / totalVotes),\n details: `${String(agents.length)} agents voting identically: ${signature}`,\n });\n emitCollusionSuspected(this.eventBus, {\n groupAgentIds: agents,\n groupSize: agents.length,\n votingBlock: agents.length / totalVotes,\n threshold: 0.6,\n });\n }\n }\n}\n\n/** Create a weighted voting instance. */\nexport function createWeightedVoting(options?: WeightedVotingOptions): IWeightedVoting {\n return new WeightedVoting(options);\n}\n","/**\n * nexus-agents/consensus - Correlation Helpers\n *\n * Helper functions for correlation tracking and independent subset partitioning.\n * Extracted from correlation-tracker.ts to maintain file size limits.\n *\n * @module consensus/correlation-helpers\n * (Source: Issue #339)\n */\n\nimport type {\n CorrelationMatrix,\n CorrelationCoefficient,\n IndependentSubset,\n VotingObservation,\n HigherOrderVotingConfig,\n AgentPairKey,\n} from './higher-order-types.js';\nimport { createAgentPairKey } from './higher-order-types.js';\n\n// ============================================================================\n// Pairwise History Types\n// ============================================================================\n\n/**\n * Internal mutable representation of pairwise history.\n */\nexport interface MutablePairwiseHistory {\n pairKey: AgentPairKey;\n jointObservations: number;\n agreements: number;\n disagreements: number;\n correlation: CorrelationCoefficient;\n lastUpdated: Date;\n}\n\n// ============================================================================\n// Vote Agreement\n// ============================================================================\n\n/**\n * Check if two observations are comparable (neither is an abstain).\n * Abstain votes should be excluded from correlation tracking.\n *\n * @param obsA - First observation\n * @param obsB - Second observation\n * @returns True if both observations have non-abstain decisions\n */\nexport function isComparable(obsA: VotingObservation, obsB: VotingObservation): boolean {\n return obsA.decision !== 'abstain' && obsB.decision !== 'abstain';\n}\n\n/**\n * Check if two votes agree.\n * Only call this after verifying isComparable() returns true.\n * Abstains are treated as neutral - neither agree nor disagree.\n *\n * @param obsA - First observation\n * @param obsB - Second observation\n * @returns True if votes agree, null if either is an abstain (neutral)\n */\nexport function votesAgree(obsA: VotingObservation, obsB: VotingObservation): boolean | null {\n if (obsA.decision === 'abstain' || obsB.decision === 'abstain') {\n return null; // Neutral — skip this pair (Issue #763)\n }\n return obsA.decision === obsB.decision;\n}\n\n/**\n * Check if a decision aligned with the outcome.\n *\n * @param decision - The voting decision\n * @param outcome - The final outcome\n * @returns True if decision aligned with outcome\n */\nexport function didAlignWithOutcome(decision: string, outcome: 'approved' | 'rejected'): boolean {\n if (decision === 'abstain') return true;\n return (\n (decision === 'approve' && outcome === 'approved') ||\n (decision === 'reject' && outcome === 'rejected')\n );\n}\n\n// ============================================================================\n// Correlation Computation\n// ============================================================================\n\n/**\n * Compute correlation coefficient from pairwise history.\n *\n * Simple correlation: (agreements - disagreements) / total\n * Range: -1 (always disagree) to +1 (always agree)\n *\n * @param history - Pairwise history\n * @returns Correlation coefficient\n */\nexport function computeCorrelationCoefficient(\n history: MutablePairwiseHistory\n): CorrelationCoefficient {\n const n = history.jointObservations;\n if (n === 0) return 0;\n\n // Map agreement/disagreement rates to [-1, 1] correlation\n // 0.5 agreement rate = 0 correlation (random)\n // 1.0 agreement rate = +1 correlation (perfect agreement)\n // 0.0 agreement rate = -1 correlation (perfect disagreement)\n const agreementRate = history.agreements / n;\n const disagreementRate = history.disagreements / n;\n\n return agreementRate - disagreementRate;\n}\n\n// ============================================================================\n// Independent Subset Partitioning\n// ============================================================================\n\n/**\n * Check if an agent is independent from all members of a subset.\n *\n * @param agent - Agent to check\n * @param subset - Existing subset members\n * @param correlationMatrix - Correlation matrix\n * @param independenceThreshold - Maximum correlation for independence\n * @returns True if agent is independent from subset\n */\nexport function isIndependentFromSubset(\n agent: string,\n subset: readonly string[],\n correlationMatrix: CorrelationMatrix,\n independenceThreshold: number\n): boolean {\n for (const member of subset) {\n const pairKey = createAgentPairKey(agent, member);\n const correlation = correlationMatrix.get(pairKey);\n\n // If we don't have data, assume independent\n if (correlation === undefined) continue;\n\n // If correlation exceeds threshold, not independent\n if (Math.abs(correlation) > independenceThreshold) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Compute the average absolute correlation within a subset.\n *\n * @param subset - Agent IDs in the subset\n * @param correlationMatrix - Correlation matrix\n * @returns Average absolute correlation (0 if no pairs)\n */\nexport function computeSubsetIndependenceScore(\n subset: readonly string[],\n correlationMatrix: CorrelationMatrix\n): number {\n if (subset.length < 2) return 0;\n\n let totalCorrelation = 0;\n let pairs = 0;\n\n for (let i = 0; i < subset.length; i++) {\n for (let j = i + 1; j < subset.length; j++) {\n const agentA = subset[i];\n const agentB = subset[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n const correlation = correlationMatrix.get(pairKey);\n if (correlation !== undefined) {\n totalCorrelation += Math.abs(correlation);\n pairs++;\n }\n }\n }\n }\n\n return pairs > 0 ? totalCorrelation / pairs : 0;\n}\n\n/**\n * Compute the minimum observation count for pairs within a subset.\n *\n * @param subset - Agent IDs in the subset\n * @param pairwiseHistory - Map of pairwise histories\n * @returns Minimum observation count (0 if no history)\n */\nexport function computeSubsetObservationCount(\n subset: readonly string[],\n pairwiseHistory: ReadonlyMap<AgentPairKey, MutablePairwiseHistory>\n): number {\n let minObservations = Infinity;\n\n for (let i = 0; i < subset.length; i++) {\n for (let j = i + 1; j < subset.length; j++) {\n const agentA = subset[i];\n const agentB = subset[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n const history = pairwiseHistory.get(pairKey);\n if (history !== undefined) {\n minObservations = Math.min(minObservations, history.jointObservations);\n } else {\n minObservations = 0;\n }\n }\n }\n }\n\n return minObservations === Infinity ? 0 : minObservations;\n}\n\n/**\n * Partition agents into independent groups using greedy clustering.\n *\n * @param agents - List of agent IDs\n * @param correlationMatrix - Correlation matrix\n * @param pairwiseHistory - Map of pairwise histories\n * @param config - Higher-order voting configuration\n * @returns Array of independent subsets\n */\nexport function partitionIntoIndependentGroups(\n agents: readonly string[],\n correlationMatrix: CorrelationMatrix,\n pairwiseHistory: ReadonlyMap<AgentPairKey, MutablePairwiseHistory>,\n config: HigherOrderVotingConfig\n): IndependentSubset[] {\n if (agents.length === 0) return [];\n\n const subsets: IndependentSubset[] = [];\n const assigned = new Set<string>();\n let subsetId = 0;\n\n for (const agent of agents) {\n if (assigned.has(agent)) continue;\n\n const subset: string[] = [agent];\n assigned.add(agent);\n\n // Try to add other unassigned agents if they're independent\n for (const other of agents) {\n if (assigned.has(other)) continue;\n if (isIndependentFromSubset(other, subset, correlationMatrix, config.independenceThreshold)) {\n subset.push(other);\n assigned.add(other);\n }\n }\n\n const independenceScore = computeSubsetIndependenceScore(subset, correlationMatrix);\n const observationCount = computeSubsetObservationCount(subset, pairwiseHistory);\n\n subsets.push({\n id: `subset-${String(subsetId++)}`,\n agentIds: subset,\n independenceScore,\n observationCount,\n });\n }\n\n return subsets;\n}\n","/**\n * nexus-agents/consensus - Correlation Tracker\n *\n * Tracks voting history and computes pairwise correlations between agents.\n * Used by higher-order voting methods to account for agent dependencies.\n *\n * @module consensus/correlation-tracker\n * (Source: Issue #333)\n */\n\nimport { createLogger } from '../core/logger.js';\nimport { getTimeProvider, getRandomProvider } from '../core/index.js';\nimport type { Vote } from './types-core.js';\nimport type {\n ICorrelationTracker,\n CorrelationMatrix,\n CorrelationCoefficient,\n IndependentSubset,\n VotingObservation,\n HigherOrderVotingConfig,\n CorrelationTrackerStats,\n AgentPairKey,\n} from './higher-order-types.js';\nimport { createAgentPairKey, DEFAULT_HIGHER_ORDER_CONFIG } from './higher-order-types.js';\nimport {\n type MutablePairwiseHistory,\n isComparable,\n votesAgree,\n didAlignWithOutcome,\n computeCorrelationCoefficient,\n partitionIntoIndependentGroups,\n} from './correlation-helpers.js';\n\n// Re-export helper types and functions for convenience\nexport type { MutablePairwiseHistory } from './correlation-helpers.js';\nexport {\n isComparable,\n votesAgree,\n didAlignWithOutcome,\n computeCorrelationCoefficient,\n isIndependentFromSubset,\n computeSubsetIndependenceScore,\n computeSubsetObservationCount,\n partitionIntoIndependentGroups,\n} from './correlation-helpers.js';\n\nconst logger = createLogger({ component: 'correlation-tracker' });\n\n/**\n * Correlation tracker implementation.\n * Records voting history and computes pairwise agent correlations.\n *\n * Memory bounded: uses FIFO eviction when maxObservationsPerAgent or maxProposals limits reached.\n */\nexport class CorrelationTracker implements ICorrelationTracker {\n private readonly config: HigherOrderVotingConfig;\n private readonly observations: Map<string, VotingObservation[]> = new Map();\n private readonly pairwiseHistory: Map<AgentPairKey, MutablePairwiseHistory> = new Map();\n private readonly agentProposals: Map<string, Map<string, VotingObservation>> = new Map();\n /** Ordered list of proposal IDs for FIFO eviction */\n private readonly proposalOrder: string[] = [];\n private cachedSubsets: IndependentSubset[] | null = null;\n\n constructor(config?: Partial<HigherOrderVotingConfig>) {\n this.config = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...config };\n logger.info('CorrelationTracker initialized', {\n maxObservationsPerAgent: this.config.maxObservationsPerAgent,\n maxProposals: this.config.maxProposals,\n });\n }\n\n recordVote(agentId: string, vote: Vote, outcome: 'approved' | 'rejected'): void {\n const proposalId = `proposal-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;\n const observation: VotingObservation = {\n proposalId,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n alignedWithOutcome: didAlignWithOutcome(vote.decision, outcome),\n timestamp: new Date(getTimeProvider().now()),\n };\n this.storeObservation(agentId, observation);\n this.invalidateCache();\n }\n\n recordProposalVotes(\n proposalId: string,\n votes: ReadonlyMap<string, Vote>,\n outcome: 'approved' | 'rejected'\n ): void {\n // FIFO eviction when proposal limit reached (Issue #521)\n this.evictOldProposalsIfNeeded();\n\n const proposalObservations: VotingObservation[] = [];\n\n for (const [agentId, vote] of votes) {\n const observation: VotingObservation = {\n proposalId,\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n alignedWithOutcome: didAlignWithOutcome(vote.decision, outcome),\n timestamp: new Date(getTimeProvider().now()),\n };\n this.storeObservation(agentId, observation);\n this.storeAgentProposal(agentId, proposalId, observation);\n proposalObservations.push(observation);\n }\n\n // Track proposal order for FIFO eviction\n this.proposalOrder.push(proposalId);\n\n this.updatePairwiseCorrelations(proposalId, proposalObservations);\n this.invalidateCache();\n\n logger.debug('Recorded proposal votes', {\n proposalId,\n agentCount: votes.size,\n outcome,\n totalProposals: this.proposalOrder.length,\n });\n }\n\n computeCorrelationMatrix(): CorrelationMatrix {\n const matrix: CorrelationMatrix = new Map();\n\n for (const [pairKey, history] of this.pairwiseHistory) {\n if (history.jointObservations >= this.config.minObservationsForCorrelation) {\n matrix.set(pairKey, history.correlation);\n }\n }\n\n return matrix;\n }\n\n getCorrelation(agentA: string, agentB: string): CorrelationCoefficient | undefined {\n const pairKey = createAgentPairKey(agentA, agentB);\n const history = this.pairwiseHistory.get(pairKey);\n\n if (history === undefined) return undefined;\n if (history.jointObservations < this.config.minObservationsForCorrelation) return undefined;\n\n return history.correlation;\n }\n\n identifyIndependentSubsets(): readonly IndependentSubset[] {\n if (this.cachedSubsets !== null) return this.cachedSubsets;\n\n const agents = this.getTrackedAgents();\n if (agents.length === 0) {\n this.cachedSubsets = [];\n return this.cachedSubsets;\n }\n\n const correlationMatrix = this.computeCorrelationMatrix();\n const subsets = partitionIntoIndependentGroups(\n agents,\n correlationMatrix,\n this.pairwiseHistory,\n this.config\n );\n\n this.cachedSubsets = subsets;\n logger.debug('Identified independent subsets', {\n agentCount: agents.length,\n subsetCount: subsets.length,\n });\n\n return subsets;\n }\n\n hasSufficientData(agentIds: readonly string[]): boolean {\n if (agentIds.length < 2) return true;\n\n let pairsWithData = 0;\n const totalPairs = (agentIds.length * (agentIds.length - 1)) / 2;\n\n for (let i = 0; i < agentIds.length; i++) {\n for (let j = i + 1; j < agentIds.length; j++) {\n const agentA = agentIds[i];\n const agentB = agentIds[j];\n if (agentA !== undefined && agentB !== undefined) {\n const pairKey = createAgentPairKey(agentA, agentB);\n const history = this.pairwiseHistory.get(pairKey);\n if (\n history !== undefined &&\n history.jointObservations >= this.config.minObservationsForCorrelation\n ) {\n pairsWithData++;\n }\n }\n }\n }\n\n // Require at least 50% of pairs to have sufficient data\n return pairsWithData >= totalPairs * 0.5;\n }\n\n getStats(): CorrelationTrackerStats {\n const agents = this.getTrackedAgents();\n // Used by callers to understand full correlation state\n void this.computeCorrelationMatrix();\n const subsets = this.identifyIndependentSubsets();\n\n let totalCorrelation = 0;\n let pairsWithSufficientData = 0;\n\n for (const [, history] of this.pairwiseHistory) {\n if (history.jointObservations >= this.config.minObservationsForCorrelation) {\n totalCorrelation += history.correlation;\n pairsWithSufficientData++;\n }\n }\n\n let totalObservations = 0;\n for (const obs of this.observations.values()) {\n totalObservations += obs.length;\n }\n\n return {\n totalAgents: agents.length,\n trackedPairs: this.pairwiseHistory.size,\n totalObservations,\n averageCorrelation:\n pairsWithSufficientData > 0 ? totalCorrelation / pairsWithSufficientData : 0,\n independentSubsetCount: subsets.length,\n pairsWithSufficientData,\n };\n }\n\n clear(): void {\n this.observations.clear();\n this.pairwiseHistory.clear();\n this.agentProposals.clear();\n this.proposalOrder.length = 0;\n this.cachedSubsets = null;\n logger.info('CorrelationTracker cleared');\n }\n\n // ============================================================================\n // Private helpers\n // ============================================================================\n\n /**\n * Evict oldest proposals when maxProposals limit is reached.\n * Also cleans up agentProposals entries for evicted proposals.\n */\n private evictOldProposalsIfNeeded(): void {\n while (this.proposalOrder.length >= this.config.maxProposals) {\n const evictedProposalId = this.proposalOrder.shift();\n if (evictedProposalId === undefined) break;\n\n // Clean up agentProposals for the evicted proposal\n for (const [agentId, proposalMap] of this.agentProposals) {\n if (proposalMap.has(evictedProposalId)) {\n proposalMap.delete(evictedProposalId);\n // Clean up empty agent entries\n if (proposalMap.size === 0) {\n this.agentProposals.delete(agentId);\n }\n }\n }\n\n logger.debug('Evicted oldest proposal', {\n evictedProposalId,\n reason: 'maxProposals',\n remainingProposals: this.proposalOrder.length,\n });\n }\n }\n\n /**\n * Evict the oldest pairwise history entry (by lastUpdated) when\n * maxTrackedPairs limit is exceeded.\n */\n private evictOldestPair(): void {\n if (this.pairwiseHistory.size <= this.config.maxTrackedPairs) return;\n\n let oldestKey: AgentPairKey | undefined;\n let oldestTime = Infinity;\n for (const [key, history] of this.pairwiseHistory) {\n const time = history.lastUpdated.getTime();\n if (time < oldestTime) {\n oldestTime = time;\n oldestKey = key;\n }\n }\n if (oldestKey !== undefined) {\n this.pairwiseHistory.delete(oldestKey);\n logger.debug('Evicted oldest pairwise history entry', {\n evictedKey: oldestKey,\n reason: 'maxTrackedPairs',\n remainingPairs: this.pairwiseHistory.size,\n });\n }\n }\n\n private storeObservation(agentId: string, observation: VotingObservation): void {\n let agentObs = this.observations.get(agentId);\n if (agentObs === undefined) {\n agentObs = [];\n this.observations.set(agentId, agentObs);\n }\n\n // FIFO eviction when per-agent limit reached (Issue #521)\n while (agentObs.length >= this.config.maxObservationsPerAgent) {\n const evicted = agentObs.shift();\n if (evicted !== undefined) {\n logger.debug('Evicted oldest observation for agent', {\n agentId,\n evictedProposalId: evicted.proposalId,\n reason: 'maxObservationsPerAgent',\n });\n }\n }\n\n agentObs.push(observation);\n }\n\n private storeAgentProposal(\n agentId: string,\n proposalId: string,\n observation: VotingObservation\n ): void {\n let agentProposalMap = this.agentProposals.get(agentId);\n if (agentProposalMap === undefined) {\n agentProposalMap = new Map();\n this.agentProposals.set(agentId, agentProposalMap);\n }\n agentProposalMap.set(proposalId, observation);\n }\n\n private updatePairwiseCorrelations(proposalId: string, observations: VotingObservation[]): void {\n for (let i = 0; i < observations.length; i++) {\n for (let j = i + 1; j < observations.length; j++) {\n const obsA = observations[i];\n const obsB = observations[j];\n if (obsA === undefined || obsB === undefined) continue;\n\n const pairKey = createAgentPairKey(obsA.agentId, obsB.agentId);\n let history = this.pairwiseHistory.get(pairKey);\n\n if (history === undefined) {\n history = {\n pairKey,\n jointObservations: 0,\n agreements: 0,\n disagreements: 0,\n correlation: 0,\n lastUpdated: new Date(getTimeProvider().now()),\n };\n this.pairwiseHistory.set(pairKey, history);\n this.evictOldestPair();\n }\n\n // Skip abstain observations — they are neutral (Issue #763)\n if (!isComparable(obsA, obsB)) continue;\n\n history.jointObservations++;\n const agreed = votesAgree(obsA, obsB);\n if (agreed === true) {\n history.agreements++;\n } else {\n history.disagreements++;\n }\n\n history.correlation = computeCorrelationCoefficient(history);\n history.lastUpdated = new Date(getTimeProvider().now());\n }\n }\n }\n\n private getTrackedAgents(): string[] {\n return Array.from(this.observations.keys());\n }\n\n private invalidateCache(): void {\n this.cachedSubsets = null;\n }\n}\n\n/**\n * Creates a new correlation tracker instance.\n */\nexport function createCorrelationTracker(\n config?: Partial<HigherOrderVotingConfig>\n): ICorrelationTracker {\n return new CorrelationTracker(config);\n}\n","/**\n * nexus-agents/consensus - Correlation Persistence\n *\n * Disk persistence for CorrelationTracker voting history. Enables Higher-Order\n * Voting (HOV) to accumulate correlation data across process restarts,\n * activating Bayesian correlation awareness.\n *\n * Storage: append-only JSONL at `~/.nexus-agents/voting/correlations.jsonl`\n * (mode 0o600). Each line is one `PersistedProposal`. Append-only avoids the\n * cross-process read-merge-rename race the previous `correlations.json`\n * design had (#2973): two processes voting concurrently each loaded N\n * entries, each merged their own proposal, each renamed over the same file,\n * losing the loser's proposal. Append guarantees atomic-per-line writes on\n * POSIX so concurrent writers are race-free.\n *\n * Reads dedupe by `proposalId` (last write wins) and apply FIFO eviction\n * past `maxProposals`. A legacy `correlations.json` is read alongside the\n * JSONL on first load (its entries are surfaced like any other history) and\n * is removed by `compactCorrelationData()` after consolidation. New writes\n * always go to the JSONL.\n *\n * @module consensus/correlation-persistence\n * (Source: Issue #514; #2973 for the JSONL switch)\n */\n\nimport * as fs from 'node:fs';\nimport { nexusDataPath } from '../config/nexus-data-dir.js';\nimport { z } from 'zod';\nimport type { Result } from '../core/result.js';\nimport { ok, err } from '../core/result.js';\nimport type { ILogger } from '../core/logger.js';\nimport { createLogger } from '../core/logger.js';\nimport type { ICorrelationTracker, HigherOrderVotingConfig } from './higher-order-types.js';\nimport { DEFAULT_HIGHER_ORDER_CONFIG } from './higher-order-types.js';\nimport type { Vote } from './types-core.js';\nimport { createCorrelationTracker } from './correlation-tracker.js';\n\nconst logger: ILogger = createLogger({ component: 'correlation-persistence' });\n\n/** Subdirectory name under the resolved nexus data dir for voting data. */\nconst VOTING_SUBDIR = 'voting';\n\n/** Legacy single-JSON file (pre-#2973). Still read on load; never written. */\nconst CORRELATIONS_FILE = 'correlations.json';\n\n/** Active append-only JSONL store (#2973). */\nconst CORRELATIONS_JSONL_FILE = 'correlations.jsonl';\n\n/** File permissions: user read/write only */\nconst FILE_MODE = 0o600;\n\n/** Directory permissions: user read/write/execute only */\nconst DIR_MODE = 0o700;\n\n/** Schema version for forward compatibility. Bumped to 2 with the JSONL switch. */\nconst SCHEMA_VERSION = 2;\n\n// ============================================================================\n// Persisted Data Types\n// ============================================================================\n\n/**\n * A single persisted vote within a proposal.\n */\nconst PersistedVoteSchema = z.object({\n agentId: z.string(),\n decision: z.enum(['approve', 'reject', 'abstain']),\n confidence: z.number().min(0).max(1),\n});\n\n/** Type for a persisted vote entry */\ntype PersistedVote = z.infer<typeof PersistedVoteSchema>;\n\n/**\n * A persisted proposal with its votes and outcome.\n * Stored as a replayable record so internal tracker state\n * is reconstructed through the public API.\n */\nconst PersistedProposalSchema = z.object({\n proposalId: z.string(),\n votes: z.array(PersistedVoteSchema),\n outcome: z.enum(['approved', 'rejected']),\n timestamp: z.iso.datetime(),\n});\n\n/** Type for a persisted proposal entry */\ntype PersistedProposal = z.infer<typeof PersistedProposalSchema>;\n\n/**\n * Top-level persisted correlation data structure (legacy `correlations.json`).\n * Kept exported for back-compat — the JSONL format stores `PersistedProposal`\n * directly per line and has no wrapper.\n */\nexport const PersistedCorrelationDataSchema = z.object({\n version: z.number().int().positive(),\n proposals: z.array(PersistedProposalSchema),\n savedAt: z.iso.datetime(),\n});\n\n/** Validated persisted correlation data */\nexport type PersistedCorrelationData = z.infer<typeof PersistedCorrelationDataSchema>;\n\n// ============================================================================\n// Path Helpers\n// ============================================================================\n\n/**\n * Returns the absolute path to the **legacy** correlation data file. Kept\n * for back-compat — new writes go through `getCorrelationJsonlPath()`.\n */\nexport function getCorrelationDataPath(): string {\n return nexusDataPath(VOTING_SUBDIR, CORRELATIONS_FILE);\n}\n\n/** Returns the absolute path to the active JSONL store (#2973). */\nexport function getCorrelationJsonlPath(): string {\n return nexusDataPath(VOTING_SUBDIR, CORRELATIONS_JSONL_FILE);\n}\n\n/**\n * Ensures the voting data directory exists with appropriate permissions.\n */\nfunction ensureVotingDirectory(): Result<void, Error> {\n const dirPath = nexusDataPath(VOTING_SUBDIR);\n try {\n fs.mkdirSync(dirPath, { recursive: true, mode: DIR_MODE });\n return ok(undefined);\n } catch (cause: unknown) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n return err(new Error(`Failed to create voting directory at ${dirPath}: ${error.message}`));\n }\n}\n\n// ============================================================================\n// Save (append-only, race-free across processes)\n// ============================================================================\n\n/**\n * Appends new proposals to the JSONL store. One line per proposal.\n *\n * POSIX `O_APPEND` (used implicitly by `appendFileSync` with `{flag: 'a'}`)\n * guarantees atomic writes for buffer sizes under `PIPE_BUF` (4 KB on Linux,\n * 512 B on macOS). Each line we write is a single `PersistedProposal` — well\n * under those limits in practice for the typical vote-panel size (3–7 voters).\n * Two processes calling this concurrently get all proposals persisted; no\n * read-merge-rename race possible because we never read or rename.\n *\n * @param proposals - Array of proposals with their votes and outcomes to persist\n * @param _config - Higher-order voting config (only `maxProposals` is consulted\n * on read; this writer is fully append-only)\n * @returns Result indicating success or failure\n */\nexport function saveCorrelationData(\n proposals: PersistedProposal[],\n // config kept in the signature for ABI compatibility with the legacy\n // implementation; the JSONL writer is append-only so we don't need it here.\n // FIFO truncation happens on read.\n _config: HigherOrderVotingConfig = DEFAULT_HIGHER_ORDER_CONFIG\n): Result<void, Error> {\n const dirResult = ensureVotingDirectory();\n if (!dirResult.ok) return dirResult;\n\n if (proposals.length === 0) return ok(undefined);\n\n const filePath = getCorrelationJsonlPath();\n\n try {\n const lines = proposals.map((p) => JSON.stringify(p)).join('\\n') + '\\n';\n fs.appendFileSync(filePath, lines, { encoding: 'utf-8', mode: FILE_MODE });\n\n logger.info('Correlation proposals appended', {\n path: filePath,\n proposalCount: proposals.length,\n });\n\n return ok(undefined);\n } catch (cause: unknown) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n return err(new Error(`Failed to append correlation data: ${error.message}`));\n }\n}\n\n// ============================================================================\n// Load (consolidates JSONL + legacy JSON, dedupes by proposalId, FIFO-truncates)\n// ============================================================================\n\n/** Read the legacy `correlations.json` if present; return [] otherwise. */\nfunction loadLegacyJsonProposals(): PersistedProposal[] {\n const filePath = getCorrelationDataPath();\n if (!fs.existsSync(filePath)) return [];\n\n let rawContent: string;\n try {\n rawContent = fs.readFileSync(filePath, { encoding: 'utf-8' });\n } catch (cause: unknown) {\n logger.warn('Failed to read legacy correlations.json', {\n path: filePath,\n error: cause instanceof Error ? cause.message : String(cause),\n });\n return [];\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(rawContent);\n } catch (cause: unknown) {\n logger.warn('Corrupt legacy correlations.json — skipping', {\n path: filePath,\n error: cause instanceof Error ? cause.message : String(cause),\n });\n return [];\n }\n\n const result = PersistedCorrelationDataSchema.safeParse(parsed);\n if (!result.success) {\n logger.warn('Invalid legacy correlations.json schema — skipping', {\n path: filePath,\n error: result.error.message,\n });\n return [];\n }\n return result.data.proposals;\n}\n\ntype LineResult = { kind: 'ok'; proposal: PersistedProposal } | { kind: 'skip'; reason: string };\n\n/** Parse one JSONL line into a typed result so the loader can stay below max-complexity. */\nfunction parseJsonlLine(line: string): LineResult {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch (cause: unknown) {\n return {\n kind: 'skip',\n reason: `JSON.parse: ${cause instanceof Error ? cause.message : String(cause)}`,\n };\n }\n const result = PersistedProposalSchema.safeParse(parsed);\n if (!result.success) return { kind: 'skip', reason: `schema: ${result.error.message}` };\n return { kind: 'ok', proposal: result.data };\n}\n\n/** Read JSONL store, dropping malformed lines with a warn log. */\nfunction loadJsonlProposals(): PersistedProposal[] {\n const filePath = getCorrelationJsonlPath();\n if (!fs.existsSync(filePath)) return [];\n\n let content: string;\n try {\n content = fs.readFileSync(filePath, { encoding: 'utf-8' });\n } catch (cause: unknown) {\n logger.warn('Failed to read correlations.jsonl', {\n path: filePath,\n error: cause instanceof Error ? cause.message : String(cause),\n });\n return [];\n }\n\n const lines = content.split('\\n').filter((line) => line.trim() !== '');\n const proposals: PersistedProposal[] = [];\n let skippedCount = 0;\n let firstSkipReason: string | undefined;\n\n for (const line of lines) {\n const result = parseJsonlLine(line);\n if (result.kind === 'ok') {\n proposals.push(result.proposal);\n } else {\n skippedCount++;\n firstSkipReason ??= result.reason;\n }\n }\n\n if (skippedCount > 0) {\n logger.warn('Skipped malformed lines in correlations.jsonl', {\n path: filePath,\n skippedCount,\n totalLines: lines.length,\n firstSkipReason,\n });\n }\n\n return proposals;\n}\n\n/**\n * Combines proposals from both stores, dedupes by proposalId (later wins),\n * sorts by timestamp ascending, and FIFO-truncates to `maxProposals`.\n */\nfunction consolidate(\n legacyProposals: PersistedProposal[],\n jsonlProposals: PersistedProposal[],\n maxProposals: number\n): PersistedProposal[] {\n const proposalMap = new Map<string, PersistedProposal>();\n // Legacy first, then JSONL — JSONL entries override legacy if same id.\n for (const p of legacyProposals) proposalMap.set(p.proposalId, p);\n for (const p of jsonlProposals) proposalMap.set(p.proposalId, p);\n\n const all = Array.from(proposalMap.values()).sort((a, b) =>\n a.timestamp.localeCompare(b.timestamp)\n );\n return all.length > maxProposals ? all.slice(all.length - maxProposals) : all;\n}\n\n/**\n * Loads and validates correlation data from disk. Combines the JSONL store\n * with the legacy `correlations.json` (if present). Always returns an Ok\n * result when the directory exists; an empty proposals array means \"no\n * persisted history\" (formerly the \"not found\" error case).\n */\nexport function loadCorrelationData(\n config: HigherOrderVotingConfig = DEFAULT_HIGHER_ORDER_CONFIG\n): Result<PersistedCorrelationData, Error> {\n const jsonlPath = getCorrelationJsonlPath();\n const legacyPath = getCorrelationDataPath();\n const jsonlExists = fs.existsSync(jsonlPath);\n const legacyExists = fs.existsSync(legacyPath);\n\n if (!jsonlExists && !legacyExists) {\n return err(new Error(`Correlation data file not found: ${jsonlPath}`));\n }\n\n const legacy = loadLegacyJsonProposals();\n const jsonl = loadJsonlProposals();\n const proposals = consolidate(legacy, jsonl, config.maxProposals);\n\n logger.info('Correlation data loaded', {\n legacyCount: legacy.length,\n jsonlCount: jsonl.length,\n afterDedup: proposals.length,\n });\n\n return ok({\n version: SCHEMA_VERSION,\n proposals,\n savedAt: new Date().toISOString(),\n });\n}\n\n// ============================================================================\n// Compaction (consolidate JSONL + delete legacy json)\n// ============================================================================\n\n/**\n * Rewrites the JSONL store as a deduplicated, sorted snapshot and removes\n * the legacy `correlations.json` (if present). Safe to call periodically\n * (e.g., on session shutdown) to bound the JSONL's size.\n *\n * Within-process: this is the only operation that's NOT race-free across\n * processes. Two processes both running compaction simultaneously could\n * lose appends made between the read and the rename. Callers should\n * serialize compaction — invoke from one process per data dir, or guard\n * with a lockfile.\n */\nexport function compactCorrelationData(\n config: HigherOrderVotingConfig = DEFAULT_HIGHER_ORDER_CONFIG\n): Result<{ before: number; after: number }, Error> {\n const dirResult = ensureVotingDirectory();\n if (!dirResult.ok) return dirResult;\n\n const legacy = loadLegacyJsonProposals();\n const jsonl = loadJsonlProposals();\n const proposals = consolidate(legacy, jsonl, config.maxProposals);\n const before = legacy.length + jsonl.length;\n\n const jsonlPath = getCorrelationJsonlPath();\n const tempPath = `${jsonlPath}.tmp.${String(process.pid)}`;\n const body =\n proposals.map((p) => JSON.stringify(p)).join('\\n') + (proposals.length > 0 ? '\\n' : '');\n\n try {\n fs.writeFileSync(tempPath, body, { encoding: 'utf-8', mode: FILE_MODE });\n fs.renameSync(tempPath, jsonlPath);\n if (fs.existsSync(getCorrelationDataPath())) {\n fs.unlinkSync(getCorrelationDataPath());\n }\n return ok({ before, after: proposals.length });\n } catch (cause: unknown) {\n try {\n if (fs.existsSync(tempPath)) fs.unlinkSync(tempPath);\n } catch (cleanupErr: unknown) {\n logger.debug('Failed to clean up temp file during compaction', {\n path: tempPath,\n error: cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr),\n });\n }\n const error = cause instanceof Error ? cause : new Error(String(cause));\n return err(new Error(`Failed to compact correlation data: ${error.message}`));\n }\n}\n\n// ============================================================================\n// Persistent Tracker Factory\n// ============================================================================\n\n/**\n * Replays persisted proposals into a tracker via `recordProposalVotes()`,\n * reconstructing all internal state through the public API.\n */\nfunction replayProposals(\n tracker: ICorrelationTracker,\n proposals: readonly PersistedProposal[]\n): number {\n let replayed = 0;\n\n for (const proposal of proposals) {\n const votes = new Map<string, Vote>();\n\n for (const vote of proposal.votes) {\n votes.set(vote.agentId, {\n decision: vote.decision,\n reasoning: 'replayed from persistence',\n confidence: vote.confidence,\n });\n }\n\n tracker.recordProposalVotes(proposal.proposalId, votes, proposal.outcome);\n replayed++;\n }\n\n return replayed;\n}\n\n/**\n * Creates a correlation tracker pre-loaded with persisted history.\n *\n * On first run (no persisted data), returns a fresh tracker.\n * On subsequent runs, replays all stored proposals through the\n * tracker's public API to reconstruct correlation state.\n *\n * This enables Higher-Order Voting to accumulate enough history\n * across process restarts to activate Bayesian correlation awareness.\n *\n * @param config - Optional partial higher-order voting config\n * @returns A correlation tracker with any persisted history replayed\n */\nexport function createPersistentCorrelationTracker(\n config?: Partial<HigherOrderVotingConfig>\n): ICorrelationTracker {\n const tracker = createCorrelationTracker(config);\n\n const mergedConfig = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...config };\n const loadResult = loadCorrelationData(mergedConfig);\n if (!loadResult.ok) {\n logger.info('Starting with fresh correlation tracker', {\n reason: loadResult.error.message,\n });\n return tracker;\n }\n\n const replayedCount = replayProposals(tracker, loadResult.value.proposals);\n\n logger.info('Correlation tracker restored from persistence', {\n replayedProposals: replayedCount,\n stats: tracker.getStats(),\n });\n\n return tracker;\n}\n\n// ============================================================================\n// Proposal Recording Helper\n// ============================================================================\n\n/**\n * Creates a persistable proposal record from vote data.\n *\n * Use this to build proposals that can be passed to `saveCorrelationData()`.\n *\n * @param proposalId - Unique proposal identifier\n * @param votes - Map of agent IDs to their votes\n * @param outcome - Final proposal outcome\n * @returns A persistable proposal record\n */\nexport function createPersistedProposal(\n proposalId: string,\n votes: ReadonlyMap<string, Vote>,\n outcome: 'approved' | 'rejected'\n): PersistedProposal {\n const persistedVotes: PersistedVote[] = [];\n\n for (const [agentId, vote] of votes) {\n persistedVotes.push({\n agentId,\n decision: vote.decision,\n confidence: vote.confidence,\n });\n }\n\n return {\n proposalId,\n votes: persistedVotes,\n outcome,\n timestamp: new Date().toISOString(),\n };\n}\n","/**\n * Types, schemas, and response helpers for the consensus_vote MCP tool.\n * Extracted from consensus-vote.ts for file size compliance (Issue #708).\n *\n * @module mcp/tools/consensus-vote-types\n */\n\nimport { z } from 'zod';\nimport type { AgentVoteResult, VotingResult } from '../../cli/vote-types.js';\nimport { VOTER_ROLES } from '../../cli/vote-types.js';\nimport type { HigherOrderVotingResult } from '../../consensus/higher-order-types.js';\n\n/** Maximum proposal length (memory bounds per Issue #435). */\nexport const MAX_PROPOSAL_LENGTH = 4000;\n\n// ============================================================================\n// Strategy Types\n// ============================================================================\n\n/**\n * Available consensus voting strategies.\n *\n * - `simple_majority`: Standard majority voting (>50%)\n * - `supermajority`: Requires >=67% approval\n * - `unanimous`: Requires 100% approval\n * - `proof_of_learning`: Weighted by agent performance (Issue #103)\n * - `higher_order`: Bayesian-optimal with correlation awareness (Issue #514)\n * - `opinion_wise`: Alias for higher_order (Issue #333)\n */\nexport type VotingStrategy =\n | 'simple_majority'\n | 'supermajority'\n | 'unanimous'\n | 'proof_of_learning'\n | 'higher_order'\n | 'opinion_wise';\n\nexport const VotingStrategySchema = z.enum([\n 'simple_majority',\n 'supermajority',\n 'unanimous',\n 'proof_of_learning',\n 'higher_order',\n 'opinion_wise',\n]);\n\n/**\n * Whether a strategy uses higher-order (Bayesian, correlation-aware) aggregation.\n * `opinion_wise` is a documented alias of `higher_order` (#333), so both must\n * take the higher-order path — gating on the literal `'higher_order'` silently\n * dropped opinion_wise to the plain engine with no higherOrderMetadata (#3271).\n */\nexport function isHigherOrderStrategy(strategy: VotingStrategy): boolean {\n return strategy === 'higher_order' || strategy === 'opinion_wise';\n}\n\n/**\n * Posterior-approval floor below which a `higher_order` quickMode *approval* is\n * escalated to the full voter panel (#3174). For Bayesian aggregation the\n * posterior is a first-class confidence signal: an approval whose posterior sits\n * near 0.5 means the 3-voter quick panel was barely decisive, which is exactly\n * the case where the extra voters are worth their cost. Mirrors the bare-constant\n * style of `CONTRARIAN_ESCALATION_THRESHOLD`. Set above any real posterior to\n * always escalate, or — since the gate also requires `posterior < floor` — a\n * floor of `0` disables posterior-based escalation entirely.\n */\nexport const HIGHER_ORDER_ESCALATION_POSTERIOR_FLOOR = 0.65;\n\n/**\n * Whether a quickMode approval should escalate to the full panel purely on a\n * borderline Bayesian posterior (#3174). Independent of the contrarian-agent\n * check — this catches low-confidence higher_order approvals that a clean\n * outcome string hides. Only fires for higher_order/opinion_wise (the strategies\n * with a meaningful posterior), on approvals, in quickMode, when the posterior\n * is known and below the floor.\n */\nexport function shouldEscalateLowPosterior(\n strategy: VotingStrategy,\n outcome: 'approved' | 'rejected',\n quickMode: boolean,\n posteriorApproval: number | undefined\n): boolean {\n return (\n quickMode &&\n outcome === 'approved' &&\n isHigherOrderStrategy(strategy) &&\n posteriorApproval !== undefined &&\n posteriorApproval < HIGHER_ORDER_ESCALATION_POSTERIOR_FLOOR\n );\n}\n\n// ============================================================================\n// Input / Output Schemas\n// ============================================================================\n\n/**\n * How error-source votes (timed-out or crashed voters) are counted toward\n * the threshold (#2630).\n *\n * - `reduce_denominator` (default for non-strict strategies): errors are\n * filtered out before the engine sees votes — denominator = non-error\n * votes. Best for operational decisions where you trust the responding\n * voters and infrastructure flake should not block the vote.\n * - `count_as_abstain`: error votes reach the engine as abstain. Behaves\n * conservatively — a timed-out voter effectively withholds approval\n * relative to the threshold. Use when you can't tell what the error\n * voter would have decided and want the math to reflect uncertainty.\n * - `fail_closed` (default for unanimous / higher_order): any error voids\n * the vote. Threshold math is not run. Use for security-critical or\n * breaking-change decisions where every voter must be heard.\n *\n * Regardless of policy, a hard floor applies: when errors exceed 50% of\n * total voters, the vote always fails. Catches \"all CLIs are down\" — a\n * 2-voter consensus is not a real consensus.\n */\nexport const ErrorPolicySchema = z.enum(['reduce_denominator', 'count_as_abstain', 'fail_closed']);\n\nexport type ErrorPolicy = z.infer<typeof ErrorPolicySchema>;\n\n/**\n * Threshold values accepted by the `--threshold` CLI flag and the\n * \\`threshold\\` MCP input field (#2638 — single source of truth).\n *\n * Maps to consensus algorithms via:\n * `majority → simple_majority`, `supermajority → supermajority`, `unanimous → unanimous`.\n *\n * Used as the canonical Zod schema for CLI parsing\n * (`cli.ts:parseThreshold`), validation (`cli-commands-validators.ts:isValidThreshold`),\n * and the `ConsensusVoteInputSchema.threshold` field.\n */\nexport const VoteThresholdSchema = z.enum(['majority', 'supermajority', 'unanimous']);\n\nexport type VoteThreshold = z.infer<typeof VoteThresholdSchema>;\n\n/**\n * Fraction of total voters that, if errored, forces the vote to fail\n * regardless of `errorPolicy`. (#2630 — safety floor.)\n */\nexport const ERROR_FLOOR_FRACTION = 0.5;\n\n/**\n * Default error policy per voting strategy.\n *\n * Only `unanimous` defaults to `fail_closed`: a missing/errored voter genuinely\n * breaks the unanimity guarantee, so the vote must void. Every other strategy —\n * including `higher_order` and its `opinion_wise` alias — defaults to\n * `reduce_denominator`: Bayesian/weighted aggregation over the *non-error*\n * voters is well-defined, so a single infra timeout (e.g. one slow voter's\n * adapter transport, #3304) should NOT fail-close an otherwise-unanimous result\n * (#3138). The >50% `ERROR_FLOOR_FRACTION` hard floor still voids any vote where\n * most voters errored. Callers can override via the `errorPolicy` input.\n */\nexport function getDefaultErrorPolicy(strategy: VotingStrategy): ErrorPolicy {\n if (strategy === 'unanimous') {\n return 'fail_closed';\n }\n return 'reduce_denominator';\n}\n\nexport const ConsensusVoteInputSchema = z.object({\n proposal: z.string().min(1).max(MAX_PROPOSAL_LENGTH).describe('Proposal text to vote on'),\n threshold: VoteThresholdSchema.optional().describe(\n 'Voting threshold (legacy): majority, supermajority, unanimous. Use strategy instead.'\n ),\n strategy: VotingStrategySchema.optional().describe(\n 'Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order (Bayesian-optimal)'\n ),\n errorPolicy: ErrorPolicySchema.optional().describe(\n 'How to treat voters that errored or timed out (#2630). Default: fail_closed for unanimous only; reduce_denominator for all other strategies incl. higher_order/opinion_wise (#3138 — a single infra timeout should not void an otherwise-unanimous vote). Regardless of policy, errors > 50% always fails.'\n ),\n quickMode: z\n .boolean()\n .optional()\n .default(false)\n .describe('Use 3 agents instead of the full 7-role panel for faster execution'),\n simulateVotes: z\n .boolean()\n .optional()\n .default(false)\n .describe(\n 'TESTS ONLY — when true, voters return random decisions. Output must not be used for real decisions. (#2319)'\n ),\n /**\n * Async-mode dispatch (#3045, Stage 4 of epic #2631). Default `sync` —\n * backward-compat invariant. `async` returns `{ status: 'pending', jobId }`\n * immediately; caller polls `get_job_result(jobId)`. Per-tool cap via\n * `NEXUS_JOB_MAX_CONCURRENT_CONSENSUS_VOTE` (default 2 — voting is\n * 7-fan-out so concurrent jobs multiply adapter load fast).\n *\n * Cancellation semantics (#3041 vote deferred this to Stage 4): when\n * a polling client calls `cancel_job` mid-vote, the dispatcher aborts\n * in-flight voters via the AbortSignal plumbing from #3038. The\n * resulting job result is `{ status: 'cancelled', partialVotes: [...] }`\n * with whatever voters completed before the abort signal — preserves\n * audit visibility into who voted before the cancel landed.\n *\n * Kept optional (no `.default()`) so the inferred type doesn't force\n * `mode: 'sync'` on every existing call site / test fixture.\n */\n mode: z\n .enum(['sync', 'async'])\n .optional()\n .describe(\n 'Dispatch mode (default: sync). Use \"async\" for higher-order strategies with 7 voters.'\n ),\n /**\n * Idempotency key for async-mode replay-safety (#3042 Stage 1c / epic\n * #2631). When set: identical (key, inputs) returns the existing job;\n * same key with different inputs fails closed with\n * `idempotency_key_collision`. Sync mode ignores this.\n */\n idempotencyKey: z\n .string()\n .min(1)\n .max(256)\n .optional()\n .describe(\n 'Replay-safe key for async-mode dispatch (#3042 Stage 1c). Same (key, inputs) returns existing jobId.'\n ),\n});\n\nexport type ConsensusVoteInput = z.infer<typeof ConsensusVoteInputSchema>;\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface AgentVoteSummary {\n role: string;\n decision: 'approve' | 'reject' | 'abstain';\n confidence: number;\n reasoning: string;\n simulated: boolean;\n /** True when this vote was generated from an error (Issue #815). */\n error: boolean;\n /** Model used for this agent's vote (Issue #817). */\n modelUsed?: string;\n /** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */\n rejectionCategories?: readonly string[];\n}\n\nexport type VoteDecisionStatus = 'approved' | 'rejected' | 'pending' | 'timeout' | 'no_quorum';\n\n/** Higher-Order Voting metadata (Issue #514). */\nexport interface HigherOrderMetadata {\n posteriorApproval: number;\n posteriorRejection: number;\n effectiveVoteCount: number;\n method: 'ow' | 'isp' | 'simple';\n usedCorrelationData: boolean;\n improvementOverBaseline: number;\n downweightedAgents: readonly string[];\n reasoning: string;\n}\n\nexport interface ConsensusVoteResponse {\n proposal: string;\n threshold?: VoteThreshold;\n strategy: VotingStrategy;\n decision: VoteDecisionStatus;\n approvalPercentage: number;\n voteCounts: { approve: number; reject: number; abstain: number; error: number };\n votes: AgentVoteSummary[];\n durationMs: number;\n simulateVotes: boolean;\n higherOrderMetadata?: HigherOrderMetadata;\n /**\n * Set when an error policy short-circuited the vote (#2630/#3124). Explains a\n * `rejected` decision that may coexist with a high `approvalPercentage` — e.g.\n * `fail_closed: 1 voter(s) errored`. Absent on normally-tallied votes.\n */\n policyReason?: string;\n /**\n * Set when the panel was DEGRADED (#3587): some voters errored, so the\n * decision rests on fewer than the requested number of voters. Surfaces a\n * silently-shrunk panel so the result isn't read as a full-strength consensus.\n * Absent when every requested voter returned a real vote.\n */\n panelWarning?: string;\n}\n\n/** Extended voting result with optional Higher-Order metadata. */\nexport interface ExtendedVotingResult extends VotingResult {\n strategy: VotingStrategy;\n higherOrderResult?: HigherOrderVotingResult;\n /** Reason an error policy short-circuited the vote (#3124); surfaced on the response. */\n policyReason?: string;\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/** Converts AgentVoteResult to AgentVoteSummary for response. */\nexport function toAgentVoteSummary(result: AgentVoteResult): AgentVoteSummary {\n const roleName = VOTER_ROLES[result.role].split(' - ')[0] ?? result.role;\n return {\n role: roleName,\n decision: result.vote.decision,\n confidence: result.vote.confidence,\n reasoning: result.vote.reasoning,\n simulated: result.source === 'simulation',\n error: result.source === 'error',\n ...(result.vote.rejectionCategories !== undefined\n ? { rejectionCategories: result.vote.rejectionCategories }\n : {}),\n };\n}\n\n/** Maps ProposalStatus to VoteDecisionStatus. */\nexport function mapOutcomeToDecision(outcome: string): VoteDecisionStatus {\n switch (outcome) {\n case 'approved':\n return 'approved';\n case 'rejected':\n return 'rejected';\n case 'timeout':\n return 'timeout';\n default:\n return 'pending';\n }\n}\n\n/**\n * #3587: partial panel degradation — some (but not all) voters errored, so the\n * decision rests on fewer voters than requested. Returns a warning string, or\n * undefined when the panel is full or entirely errored (the latter is already a\n * structured error elsewhere).\n */\nfunction panelDegradationWarning(errorCount: number, total: number): string | undefined {\n if (errorCount <= 0 || errorCount >= total) return undefined;\n return (\n `Panel degraded: ${String(errorCount)} of ${String(total)} voters errored; ` +\n `decision rests on ${String(total - errorCount)} voter(s).`\n );\n}\n\n/** Builds the response from voting result. */\nexport function buildResponse(\n input: ConsensusVoteInput,\n result: ExtendedVotingResult\n): ConsensusVoteResponse {\n const proposalTruncated =\n input.proposal.length > 200 ? input.proposal.slice(0, 200) + '...' : input.proposal;\n\n const errorCount = result.votes.filter((v) => v.source === 'error').length;\n\n const allErrors = errorCount === result.votes.length && errorCount > 0;\n const decision: VoteDecisionStatus =\n !result.result.quorumReached && allErrors\n ? 'no_quorum'\n : mapOutcomeToDecision(result.result.outcome);\n\n const response: ConsensusVoteResponse = {\n proposal: proposalTruncated,\n strategy: result.strategy,\n decision,\n approvalPercentage: result.result.approvalPercentage,\n voteCounts: {\n approve: result.result.voteCounts.approve,\n reject: result.result.voteCounts.reject,\n abstain: result.result.voteCounts.abstain,\n error: errorCount,\n },\n votes: result.votes.map(toAgentVoteSummary),\n durationMs: result.totalTimeMs,\n simulateVotes: result.simulateVotes,\n };\n\n if (input.threshold !== undefined) {\n response.threshold = input.threshold;\n }\n\n if (result.policyReason !== undefined) {\n response.policyReason = result.policyReason;\n }\n\n const panelWarning = panelDegradationWarning(errorCount, result.votes.length);\n if (panelWarning !== undefined) {\n response.panelWarning = panelWarning;\n }\n\n if (isHigherOrderStrategy(result.strategy) && result.higherOrderResult) {\n response.higherOrderMetadata = toHigherOrderMetadata(result.higherOrderResult);\n }\n\n return response;\n}\n\n/** Maps a HigherOrderVotingResult to the response's metadata shape. */\nfunction toHigherOrderMetadata(r: HigherOrderVotingResult): HigherOrderMetadata {\n return {\n posteriorApproval: r.posteriorApproval,\n posteriorRejection: r.posteriorRejection,\n effectiveVoteCount: r.effectiveVoteCount,\n method: r.method,\n usedCorrelationData: r.usedCorrelationData,\n improvementOverBaseline: r.improvementOverBaseline,\n downweightedAgents: r.downweightedAgents,\n reasoning: r.reasoning,\n };\n}\n","/**\n * Error-policy handling for consensus_vote (#2630).\n *\n * When a voter errors or times out (`source === 'error'`), the response\n * shape already distinguishes it via `voteCounts.error` (see\n * consensus-vote-types.ts:188). What was missing: a configurable\n * decision policy for how those error voters interact with the strategy\n * threshold, plus a safety floor for \"too many errors to call a\n * consensus.\"\n *\n * Three policies, plus a hard floor:\n *\n * - `reduce_denominator` (default for non-strict strategies): errors\n * filtered out before the engine sees votes. Denominator = non-error\n * votes. Pragmatic for operational decisions.\n * - `count_as_abstain`: errors reach the engine as abstain. Conservative\n * — error voter is treated as having withheld approval.\n * - `fail_closed` (default for unanimous only, #3138): any error\n * short-circuits to vote-void.\n *\n * Hard floor: if errors > `ERROR_FLOOR_FRACTION` of total voters, the\n * vote always fails regardless of policy. \"All CLIs are down\" is not a\n * consensus.\n *\n * @module mcp/tools/consensus-vote-error-policy\n */\n\nimport type { AgentVoteResult } from '../../cli/vote-types.js';\nimport type { ErrorPolicy } from './consensus-vote-types.js';\nimport { ERROR_FLOOR_FRACTION } from './consensus-vote-types.js';\n\nexport interface ErrorPolicyDecision {\n /** True when the vote should short-circuit to failed without reaching the engine. */\n readonly shortCircuit: boolean;\n /** Human-readable reason when shortCircuit is true. */\n readonly reason?: string;\n /**\n * Votes to feed to the engine. Empty when shortCircuit is true.\n * Otherwise: errors filtered out (`reduce_denominator`) or converted\n * to abstain (`count_as_abstain`).\n */\n readonly engineVotes: readonly AgentVoteResult[];\n}\n\nfunction isHardFloorTripped(errorCount: number, totalCount: number): boolean {\n if (totalCount === 0) return false;\n return errorCount / totalCount > ERROR_FLOOR_FRACTION;\n}\n\n/**\n * Apply the configured error policy to the raw voter list. Returns a\n * decision describing whether the vote should short-circuit and what\n * votes (if any) should reach the consensus engine.\n *\n * The hard floor (`errors / total > ERROR_FLOOR_FRACTION`) takes\n * precedence over any policy — even `reduce_denominator` short-circuits\n * when most voters errored, because the remaining minority isn't a real\n * consensus.\n *\n * The per-voter response list is built from the ORIGINAL `votes` array\n * upstream; this helper only shapes what the engine sees.\n */\nexport function applyErrorPolicy(\n votes: readonly AgentVoteResult[],\n policy: ErrorPolicy\n): ErrorPolicyDecision {\n const errorVotes = votes.filter((v) => v.source === 'error');\n const errorCount = errorVotes.length;\n const totalCount = votes.length;\n\n if (isHardFloorTripped(errorCount, totalCount)) {\n return {\n shortCircuit: true,\n reason: `Errors exceeded ${String(Math.round(ERROR_FLOOR_FRACTION * 100))}% of voters (${String(errorCount)}/${String(totalCount)})`,\n engineVotes: [],\n };\n }\n\n if (policy === 'fail_closed' && errorCount > 0) {\n return {\n shortCircuit: true,\n reason: `fail_closed: ${String(errorCount)} voter(s) errored`,\n engineVotes: [],\n };\n }\n\n if (policy === 'count_as_abstain') {\n // Errors stay in the engine input but as abstain decisions.\n // The original `source: 'error'` is preserved so the per-voter\n // response shape and `voteCounts.error` still report the error.\n return {\n shortCircuit: false,\n engineVotes: votes.map((v) =>\n v.source === 'error' ? { ...v, vote: { ...v.vote, decision: 'abstain' as const } } : v\n ),\n };\n }\n\n // reduce_denominator (default): errors filtered out before engine sees them.\n return {\n shortCircuit: false,\n engineVotes: votes.filter((v) => v.source !== 'error'),\n };\n}\n","/**\n * Persistent OutcomeStore — JSONL-backed cross-session persistence.\n *\n * Extends the in-memory OutcomeStore with disk-backed append-only\n * JSONL storage. Hydrates on construction, appends on every write.\n * Corrupt lines are skipped with a warning (graceful degradation).\n *\n * @module orchestration/outcomes/outcome-store-persistence\n * (Source: Issue #1009 — Cross-session persistence)\n */\n\nimport { appendFileSync, readFileSync, writeFileSync, existsSync } from 'node:fs';\n\nimport type { ILogger } from '../../core/index.js';\nimport { createLogger, getErrorMessage } from '../../core/index.js';\nimport { TaskOutcomeSchema } from './outcome-types.js';\nimport type { TaskOutcome } from './outcome-types.js';\nimport { OutcomeStore, registerPersistentOutcomeStoreFactory } from './outcome-store.js';\nimport type { OutcomeStoreConfig } from './outcome-store.js';\nimport { ensureLearningDir, getOutcomesFile } from '../../config/learning-persistence.js';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\nexport interface PersistentOutcomeStoreConfig extends OutcomeStoreConfig {\n /** Override the file path (useful for testing). */\n readonly filePath?: string;\n /** Override the data directory (useful for testing). */\n readonly dataDir?: string;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * OutcomeStore that persists entries to a JSONL file on disk.\n *\n * - Construction: hydrates from existing JSONL file (Zod-validates each line)\n * - Append: calls super.append() then appendFileSync one JSON line\n * - Corruption: bad lines are skipped with a warning log\n */\nexport class PersistentOutcomeStore extends OutcomeStore {\n private readonly filePath: string;\n private readonly logger: ILogger;\n\n constructor(config?: PersistentOutcomeStoreConfig, logger?: ILogger) {\n super(config);\n this.filePath = config?.filePath ?? getOutcomesFile();\n this.logger = logger ?? createLogger({ component: 'PersistentOutcomeStore' });\n\n const dataDir = config?.dataDir;\n ensureLearningDir(dataDir);\n this.hydrate();\n this.reclassifyHydrated();\n this.purgeSkippedOnHydrate();\n }\n\n /** Override append to persist each entry to disk. */\n override append(outcome: TaskOutcome): void {\n super.append(outcome);\n this.persistLine(outcome);\n }\n\n // ==========================================================================\n // Private\n // ==========================================================================\n\n /**\n * Reclassify hydrated entries that lack a failureCategory.\n * Bounded: reclassifyAll() skips success outcomes and already-classified\n * entries, so only unclassified failures are processed (#1457).\n */\n /**\n * Purge false failures from skipped workers on hydration (#1528).\n * These are 0ms non-success worker-* entries created before the\n * recording fix, representing routing decisions not real failures.\n */\n private purgeSkippedOnHydrate(): void {\n if (this.size === 0) return;\n const purged = this.purgeSkippedWorkers();\n if (purged > 0) {\n this.logger.info('Purged skipped-worker false failures from history', { purged });\n this.rewriteFile();\n }\n }\n\n private reclassifyHydrated(): void {\n if (this.size === 0) return;\n const reclassified = this.reclassifyAll();\n if (reclassified > 0) {\n this.logger.info('Reclassified hydrated outcomes with updated categories', {\n reclassified,\n });\n this.rewriteFile();\n }\n }\n\n private hydrate(): void {\n if (!existsSync(this.filePath)) {\n this.logger.debug('No outcomes file found, starting fresh', {\n path: this.filePath,\n });\n return;\n }\n\n try {\n const content = readFileSync(this.filePath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim().length > 0);\n let loaded = 0;\n let skipped = 0;\n\n for (const line of lines) {\n try {\n const parsed: unknown = JSON.parse(line);\n const result = TaskOutcomeSchema.safeParse(parsed);\n if (result.success) {\n super.append(result.data);\n loaded++;\n } else {\n skipped++;\n }\n } catch (parseErr: unknown) {\n this.logger.debug('Skipping malformed outcome line during hydration', {\n error: getErrorMessage(parseErr),\n linePreview: line.slice(0, 80),\n });\n skipped++;\n }\n }\n\n this.logger.info('Hydrated outcomes from disk', {\n loaded,\n skipped,\n total: lines.length,\n path: this.filePath,\n });\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n this.logger.warn('Failed to hydrate outcomes from disk', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n\n /** Rewrite the JSONL file from in-memory state after reclassification. */\n private rewriteFile(): void {\n try {\n const entries = this.query();\n const content = entries.map((e) => JSON.stringify(e)).join('\\n') + '\\n';\n writeFileSync(this.filePath, content, 'utf-8');\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n this.logger.warn('Failed to rewrite outcomes file after reclassification', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n\n private persistLine(outcome: TaskOutcome): void {\n try {\n appendFileSync(this.filePath, JSON.stringify(outcome) + '\\n', 'utf-8');\n } catch (error: unknown) {\n const msg = getErrorMessage(error);\n this.logger.warn('Failed to persist outcome to disk', {\n error: msg,\n path: this.filePath,\n });\n }\n }\n}\n\n// Self-register factory so getOutcomeStore() can create PersistentOutcomeStore\n// without a circular top-level import.\nregisterPersistentOutcomeStoreFactory(() => new PersistentOutcomeStore());\n","/**\n * Consensus Vote — Recording Helpers\n *\n * Memory and outcome store recording for consensus votes.\n * Extracted from consensus-vote.ts for file size compliance.\n *\n * @module mcp/tools/consensus-vote-recording\n * (Source: Issue #753 memory, Issue #1134 cold start)\n */\n\nimport {\n createLogger,\n getErrorMessage,\n getTimeProvider,\n getRandomProvider,\n} from '../../core/index.js';\nimport type { AgentVoteResult } from '../../cli/vote-types.js';\nimport { getToolMemory } from './tool-memory.js';\nimport {\n getOutcomeStore,\n categorizeOutcomeErrorMessage,\n} from '../../orchestration/outcomes/index.js';\nimport {\n DEFAULT_CLI,\n CLI_NAMES,\n type CliNameLiteral,\n} from '../../config/model-capabilities-types.js';\n\nconst logger = createLogger({ tool: 'consensus-vote' });\n\n/**\n * Records a successful consensus vote to session memory AND outcome store. Best-effort.\n *\n * When every vote is simulated, this is a no-op: simulated votes are random\n * (#2319) and must not seed the learning store or outcome store, otherwise\n * test/demo runs poison real routing decisions.\n */\nexport function recordVoteSuccess(\n proposal: string,\n strategy: string,\n outcome: string,\n duration: number,\n votes?: readonly AgentVoteResult[]\n): void {\n const allSimulated =\n votes !== undefined && votes.length > 0 && votes.every((v) => v.source === 'simulation');\n if (allSimulated) {\n logger.debug('Skipping memory + outcome recording — all votes simulated');\n return;\n }\n\n try {\n const memory = getToolMemory();\n memory.recordTask({\n approach: `Consensus vote: ${strategy} on \"${proposal.slice(0, 50)}\"`,\n challenges: [],\n durationMs: duration,\n });\n memory.recordLearning({\n pattern: `${strategy} vote → ${outcome}`,\n context: `proposal=\"${proposal.slice(0, 40)}\" duration=${String(duration)}ms`,\n confidence: 0.8,\n source: 'consensus-vote',\n });\n void memory.runPromotionPipeline().catch((error: unknown) => {\n logger.warn('Promotion pipeline failed', { error });\n });\n } catch (error: unknown) {\n logger.warn('Failed to record vote success to memory', { error: getErrorMessage(error) });\n }\n\n // Also record to outcome store for adaptive routing feedback (#1551).\n // recordVoteOutcomes already filters per-vote `source === 'simulation'`,\n // but we keep the all-simulated guard above to skip the memory writes too.\n if (votes !== undefined) {\n recordVoteOutcomes(votes);\n }\n}\n\n/** Records a failed consensus vote to session memory. Best-effort. */\nexport function recordVoteError(proposal: string, errorMessage: string): void {\n try {\n const memory = getToolMemory();\n memory.recordError({\n error: `Consensus vote failed: ${errorMessage.slice(0, 150)}`,\n solution: 'Pending - vote execution failed',\n filePattern: 'mcp/tools/consensus-vote',\n });\n } catch (error: unknown) {\n logger.warn('Failed to record vote error', { error: getErrorMessage(error) });\n }\n}\n\n/**\n * Records per-vote outcomes to the outcome store for adaptive routing.\n * Each successful LLM vote contributes a sample to its CLI×category pair.\n * (Issue #1134 — cold start mitigation)\n */\nexport function recordVoteOutcomes(votes: readonly AgentVoteResult[]): void {\n try {\n const store = getOutcomeStore();\n const now = new Date().toISOString();\n for (const vote of votes) {\n if (vote.source === 'simulation') continue;\n const cliName: CliNameLiteral =\n vote.cli !== undefined && (CLI_NAMES as readonly string[]).includes(vote.cli)\n ? (vote.cli as CliNameLiteral)\n : DEFAULT_CLI;\n const voteSuccess = vote.source === 'llm';\n store.append({\n id: `vote-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 8)}`,\n cli: cliName,\n category: 'planning',\n model: 'consensus',\n success: voteSuccess,\n durationMs: vote.processingTimeMs,\n timestamp: now,\n source: 'consensus',\n // #2662 — carry the voter role so the stratified outcome report\n // can break consensus results down by role.\n voterRole: vote.role,\n ...(!voteSuccess && vote.error !== undefined\n ? {\n failureCategory: categorizeOutcomeErrorMessage(vote.error),\n errorMessage: vote.error.slice(0, 500),\n }\n : {}),\n });\n }\n } catch (error: unknown) {\n logger.debug('Best-effort vote outcome recording failed', { error: getErrorMessage(error) });\n }\n}\n","/**\n * Consensus → pipeline-bus signal emitter (#3147, epic #3143 P2).\n *\n * Emits the `signal.vote_rejected` observability signal onto the typed pipeline\n * event bus when a consensus vote resolves to `rejected`, closing the\n * self-tuning loop (the shadow TuneStage consumes it). Lives at the MCP\n * integration layer ON PURPOSE: the pure `ConsensusEngine` stays decoupled from\n * the pipeline bus, preserving the `A = observability / B = messaging` boundary\n * adopted for #3289 (scope Option 2 — observability signals route through bus A,\n * the collaboration messaging bus is untouched).\n *\n * @module mcp/tools/consensus-vote-signals\n */\n\nimport { getErrorMessage, getTimeProvider } from '../../core/index.js';\nimport type { ILogger } from '../../core/index.js';\nimport type { ConsensusResult } from '../../consensus/types.js';\nimport type { IEventBus } from '../../pipeline/event-types.js';\n\n/** Distinct rejection categories across the reject votes, or undefined if none. */\nfunction rejectionRulesFrom(result: ConsensusResult): readonly string[] | undefined {\n const rules = new Set<string>();\n for (const vote of result.votes.values()) {\n if (vote.decision === 'reject' && vote.rejectionCategories !== undefined) {\n for (const category of vote.rejectionCategories) rules.add(category);\n }\n }\n return rules.size > 0 ? [...rules] : undefined;\n}\n\n/**\n * Emit `signal.vote_rejected` onto `bus` when `result.outcome === 'rejected'`.\n * No-op for any other outcome. Emission errors are swallowed and logged —\n * observability signalling must never break the vote path.\n */\nexport function emitVoteRejectedSignal(\n result: ConsensusResult,\n bus: IEventBus,\n logger: ILogger\n): void {\n if (result.outcome !== 'rejected') return;\n try {\n const rejectionRules = rejectionRulesFrom(result);\n bus.emit({\n type: 'signal.vote_rejected',\n timestamp: getTimeProvider().now(),\n proposalId: result.proposalId,\n approvalPercentage: result.approvalPercentage,\n ...(rejectionRules !== undefined ? { rejectionRules } : {}),\n });\n } catch (error) {\n logger.warn('Failed to emit signal.vote_rejected', { error: getErrorMessage(error) });\n }\n}\n","/**\n * Simulation Guard — runtime safety net for `simulateVotes: true`.\n *\n * Simulated votes are random and exist only for unit tests and demos.\n * If a caller passes `simulateVotes: true` outside a test runner, this module\n * emits a one-shot stderr warning so the misuse cannot be silent.\n * (Source: Issue #2317, #2319)\n *\n * @module mcp/tools/simulation-guard\n */\n\nimport type { ILogger } from '../../core/index.js';\n\nconst WARNED = new Set<string>();\n\n/** Returns true when running under vitest or another test runner. */\nexport function isTestRunner(): boolean {\n return process.env.VITEST === 'true' || process.env.NODE_ENV === 'test';\n}\n\n/**\n * If `simulate` is true and we are not in a test runner, log a one-shot\n * warning per (tool, process) pair via the supplied logger. Returns the\n * `simulate` value unchanged so it can be used inline.\n *\n * Why: `simulateVotes: true` is a unit-test affordance; using it as a\n * fallback when adapters are unavailable produces random \"decisions\" that\n * silently corrupt downstream behavior. A loud warning is the minimum\n * defense; #2319 also stops simulated runs from polluting tool memory.\n */\nexport function warnIfSimulatedOutsideTests(toolName: string, logger: ILogger): void {\n if (isTestRunner()) return;\n if (WARNED.has(toolName)) return;\n WARNED.add(toolName);\n logger.warn(\n `[${toolName}] simulateVotes=true: output is RANDOM and reserved for tests/demos. Do not treat the result as a real decision.`\n );\n}\n\n/** Test-only: clear the warned-set so repeated tests can re-trigger the warning. */\nexport function _resetWarned(): void {\n WARNED.clear();\n}\n","/**\n * Job-result store for async-mode MCP tools (#3042, Stage 1 of #2631).\n *\n * Persists the final result of a background-dispatched MCP tool\n * invocation to `<NEXUS_DATA_DIR>/jobs/result-<jobId>.json`. Lets a\n * caller dispatch a long-running tool via `mode: 'async'`, receive a\n * `jobId` immediately, and poll for the result via `get_job_result`\n * (or any other reader that imports `readJobResult`).\n *\n * **Why a sidecar file (not the structured-task-state log):** Stage 1\n * deliberately doesn't extend `StructuredTaskState` — that schema change\n * is Stage 2 (#3043). Putting the result in a sidecar file lets the\n * async-mode protocol ship and be validated end-to-end before the schema\n * migration lands. Once Stage 2 ships, this store can be deprecated:\n * `query_task_state` will return the result inline and the sidecar files\n * become legacy that the next cleanup sweep can remove.\n *\n * **Why per-repo storage (`jobs` is in `PER_REPO_SUBDIRS`):** a job\n * dispatched on repo A should not be pollable on repo B. The split\n * matches `tasks/state-orch-*.jsonl` which is also per-repo.\n *\n * Status lifecycle: `pending` → (`complete` | `failed` | `cancelled`).\n * `cancelled` isn't written by Stage 1 (no `cancel_job` yet — that's\n * a follow-up under the same Stage 1 umbrella) but the type space\n * carries it so the next PR doesn't churn the schema.\n *\n * @module mcp/jobs/job-result-store\n */\n\nimport { existsSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';\n\nimport { z } from 'zod';\n\nimport { createLogger } from '../../core/index.js';\nimport { nexusDataPath, nexusDataPathEnsure } from '../../config/nexus-data-dir.js';\n\nconst logger = createLogger({ component: 'job-result-store' });\n\n/** Lifecycle status of a job-result record. */\nexport const JobStatusSchema = z.enum(['pending', 'complete', 'failed', 'cancelled']);\nexport type JobStatus = z.infer<typeof JobStatusSchema>;\n\n/**\n * One on-disk job-result record. Versioned so future readers can\n * tell which Stage wrote it — bump on schema break.\n */\nexport const JobResultSchema = z.object({\n /** Format version. Currently `1` — bump if the shape changes. */\n v: z.literal(1),\n jobId: z.string().min(1),\n /** Tool that was invoked (e.g. `orchestrate`). */\n toolName: z.string().min(1),\n status: JobStatusSchema,\n createdAt: z.iso.datetime(),\n /** Set when the job leaves `pending` — either via `complete` or `failed` or `cancelled`. */\n completedAt: z.iso.datetime().optional(),\n /**\n * Structured payload the synchronous mode would have returned. Present\n * only when `status === 'complete'`. Shape is tool-specific — readers\n * cast to the tool's known output type after status check.\n */\n result: z.unknown().optional(),\n /**\n * Failure message when `status === 'failed'`. Cannot be paired with\n * `result` — the discriminator is `status`.\n */\n error: z.string().optional(),\n});\nexport type JobResult = z.infer<typeof JobResultSchema>;\n\n/** Resolve the sidecar path for a given jobId. */\nfunction jobResultPath(jobId: string): string {\n // `jobs/result-<id>.json` — single segment past `jobs/` so\n // `nexusDataPathEnsure` makes the `jobs/` directory and returns\n // the file path.\n return nexusDataPathEnsure('jobs', `result-${jobId}.json`);\n}\n\n/**\n * Write the initial `pending` record for a new job. Idempotent: if a\n * record for `jobId` already exists (e.g. operator restart re-runs the\n * same idempotencyKey — Stage 1 follow-up), this is a no-op.\n *\n * Caller responsibility: generate a fresh `jobId` per call (Stage 1\n * doesn't yet deduplicate via idempotencyKey — that's #3042 follow-up).\n */\nexport function writeJobPending(jobId: string, toolName: string): void {\n const path = jobResultPath(jobId);\n if (existsSync(path)) {\n logger.debug('Job result file already exists — leaving in place', { jobId });\n return;\n }\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'pending',\n createdAt: new Date().toISOString(),\n };\n writeFileSync(path, JSON.stringify(record, null, 2));\n logger.debug('Wrote pending job record', { jobId, toolName });\n}\n\n/**\n * Replace the record with a terminal `complete` status carrying the\n * structured payload. Caller writes the SAME shape the sync mode would\n * have returned, so a polling client can use the result interchangeably.\n */\nexport function writeJobComplete(jobId: string, toolName: string, result: unknown): void {\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'complete',\n createdAt: readJobResult(jobId)?.createdAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n result,\n };\n writeFileSync(jobResultPath(jobId), JSON.stringify(record, null, 2));\n logger.debug('Wrote complete job record', { jobId, toolName });\n}\n\n/** Terminal `failed` status. `error` is the human-readable failure message. */\nexport function writeJobFailed(jobId: string, toolName: string, error: string): void {\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'failed',\n createdAt: readJobResult(jobId)?.createdAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n error,\n };\n writeFileSync(jobResultPath(jobId), JSON.stringify(record, null, 2));\n logger.debug('Wrote failed job record', { jobId, toolName, error });\n}\n\n/**\n * Terminal `cancelled` status — set by `cancel_job` (#3042 Stage 1b).\n *\n * Idempotent-by-design at the in-memory state level: if the record is\n * already `complete` / `failed` / `cancelled`, `cancel_job` reports\n * `already_complete` / `already_cancelled` to the caller and DOES NOT\n * overwrite the terminal record (per the #3041 vote Security flag —\n * cancel-after-complete must not rewrite history).\n *\n * The caller (cancel_job tool) checks the current status BEFORE calling\n * this; this writer trusts the caller and always overwrites. Guarding\n * here too would duplicate the guard but is cheap insurance — current\n * design: caller-side guard only.\n */\nexport function writeJobCancelled(jobId: string, toolName: string, reason?: string): void {\n const record: JobResult = {\n v: 1,\n jobId,\n toolName,\n status: 'cancelled',\n createdAt: readJobResult(jobId)?.createdAt ?? new Date().toISOString(),\n completedAt: new Date().toISOString(),\n ...(reason !== undefined ? { error: reason } : {}),\n };\n writeFileSync(jobResultPath(jobId), JSON.stringify(record, null, 2));\n logger.debug('Wrote cancelled job record', { jobId, toolName, reason });\n}\n\n/**\n * Read a job-result record. Returns `null` if the jobId is unknown\n * (file doesn't exist) or unreadable (corrupt JSON, schema mismatch).\n *\n * Schema mismatch is treated as \"not found\" not \"error\" so a client\n * polling against a future-Stage record from an older nexus-agents\n * process doesn't crash — the request just looks like an unknown jobId\n * until the operator upgrades.\n */\nexport function readJobResult(jobId: string): JobResult | null {\n const path = nexusDataPath('jobs', `result-${jobId}.json`);\n if (!existsSync(path)) return null;\n try {\n const raw = JSON.parse(readFileSync(path, 'utf-8')) as unknown;\n const parsed = JobResultSchema.safeParse(raw);\n if (!parsed.success) {\n logger.warn('Job result file failed schema check', { jobId, path });\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn('Job result file unreadable', {\n jobId,\n path,\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n\n/**\n * List job records under `<NEXUS_DATA_DIR>/jobs/` (#3046 Stage 5).\n *\n * Returns ALL records sorted by `createdAt` descending (newest first).\n * Caller filters by `toolName` / `status` via the `list_jobs` MCP tool —\n * we don't push the filter logic in here because tools change shape but\n * the store doesn't.\n *\n * **The result payloads are intentionally EXCLUDED** from each summary\n * — large complete-status records can be 1 MiB each (per Stage 2's\n * TASK_RESULT_MAX_BYTES cap), and `list_jobs` is meant for discovery,\n * not retrieval. Callers re-fetch full records via `get_job_result(jobId)`.\n *\n * Schema-mismatch + unreadable files are silently dropped (logged as\n * warnings), same policy as `readJobResult`.\n */\nexport interface JobSummary {\n readonly jobId: string;\n readonly toolName: string;\n readonly status: JobResult['status'];\n readonly createdAt: string;\n readonly completedAt?: string;\n /** True iff the record carries an error message (status === 'failed'). */\n readonly hasError: boolean;\n}\n\n/** Project a full {@link JobResult} down to its {@link JobSummary} — shared by\n * the sidecar walk here and the task-state list source (#3693). */\nexport function toJobSummary(record: JobResult): JobSummary {\n return {\n jobId: record.jobId,\n toolName: record.toolName,\n status: record.status,\n createdAt: record.createdAt,\n hasError: record.error !== undefined,\n ...(record.completedAt !== undefined ? { completedAt: record.completedAt } : {}),\n };\n}\n\nexport function listJobs(): JobSummary[] {\n const dir = nexusDataPath('jobs');\n if (!existsSync(dir)) return [];\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch (err) {\n logger.warn('jobs directory unreadable', {\n dir,\n error: err instanceof Error ? err.message : String(err),\n });\n return [];\n }\n const summaries: JobSummary[] = [];\n for (const entry of entries) {\n const match = /^result-(.+)\\.json$/.exec(entry);\n if (match === null) continue;\n const jobId = match[1];\n if (jobId === undefined) continue;\n const record = readJobResult(jobId);\n if (record === null) continue;\n summaries.push(toJobSummary(record));\n }\n // Newest first — matches typical \"what just happened\" discovery flow.\n return summaries.sort((a, b) => b.createdAt.localeCompare(a.createdAt));\n}\n","/**\n * Idempotency-key resolution for async-mode MCP tool dispatch (#3042 Stage 1c,\n * epic #2631). Lets a caller pass `idempotencyKey: \"<string>\"` and re-invoke\n * the same logical operation safely across sessions / process restarts.\n *\n * ## Contract\n *\n * - Key + matching inputs → returns the existing job's record (whatever\n * state — pending / complete / failed / cancelled). Caller polls\n * `get_job_result(jobId)` exactly as if it had dispatched fresh.\n * - Key + DIFFERENT inputs → fails closed with `idempotency_key_collision`.\n * Reusing a key with different inputs is almost certainly a caller bug;\n * silent merge would either hide a typo or leak the first call's result\n * into a second logical operation.\n * - No key → caller falls back to a fresh `randomUUID()` jobId (existing\n * behavior; this module is a no-op).\n *\n * ## Storage shape\n *\n * One file per (tool, key) tuple at:\n * `<NEXUS_DATA_DIR>/jobs/key-<sha256(tool + ':' + key)>.json`\n *\n * Record: `{ v: 1, tool, key, inputsHash, jobId, createdAt }`.\n *\n * Sharded by `(tool, key)` so two different tools using the same human key\n * don't collide. The filename is the hash so an attacker who reads the\n * directory listing can't recover the user-supplied key.\n *\n * @module mcp/jobs/job-idempotency\n */\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs';\n\nimport { z } from 'zod';\n\nimport { createLogger } from '../../core/index.js';\nimport { nexusDataPath, nexusDataPathEnsure } from '../../config/nexus-data-dir.js';\n\nconst logger = createLogger({ component: 'job-idempotency' });\n\n/** Index-file record persisted per (tool, key). */\nexport const IdempotencyIndexEntrySchema = z.object({\n v: z.literal(1),\n /** MCP tool name (e.g. `orchestrate`, `run_workflow`, `consensus_vote`). */\n tool: z.string().min(1),\n /** Caller-supplied idempotency key. */\n key: z.string().min(1),\n /** sha256 of the canonical input JSON. */\n inputsHash: z.string().length(64),\n /** Existing jobId for this (tool, key, inputs) tuple. */\n jobId: z.string().min(1),\n /** ISO timestamp of first dispatch. */\n createdAt: z.iso.datetime(),\n});\nexport type IdempotencyIndexEntry = z.infer<typeof IdempotencyIndexEntrySchema>;\n\n/** Outcome of `resolveIdempotency` — discriminated by `kind`. */\nexport type IdempotencyResolution =\n | { readonly kind: 'fresh'; readonly jobId: string }\n | { readonly kind: 'replay'; readonly jobId: string; readonly entry: IdempotencyIndexEntry }\n | {\n readonly kind: 'collision';\n readonly existingInputsHash: string;\n readonly incomingInputsHash: string;\n readonly existingJobId: string;\n };\n\n/** sha256 hex of a string. */\nfunction sha256Hex(input: string): string {\n return createHash('sha256').update(input).digest('hex');\n}\n\n/**\n * Canonical JSON serialization for input hashing. Sorts object keys\n * recursively so `{a:1,b:2}` and `{b:2,a:1}` produce identical hashes.\n *\n * `undefined` values are dropped (JSON semantics); function values throw\n * — schema validation should have caught those upstream.\n */\nfunction canonicalJsonStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return `[${value.map(canonicalJsonStringify).join(',')}]`;\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));\n return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalJsonStringify(v)}`).join(',')}}`;\n}\n\n/** Compute the inputs hash used to detect (tool, key) collisions. */\nexport function computeInputsHash(inputs: unknown): string {\n return sha256Hex(canonicalJsonStringify(inputs));\n}\n\n/** Compute the on-disk index path for a (tool, key) tuple. */\nfunction indexFilePath(tool: string, key: string): string {\n // Filename is hashed so a directory listing doesn't leak user keys.\n const filename = `key-${sha256Hex(`${tool}:${key}`)}.json`;\n return nexusDataPathEnsure('jobs', filename);\n}\n\n/** Read-only counterpart that doesn't create the parent directory. */\nfunction indexFilePathReadOnly(tool: string, key: string): string {\n const filename = `key-${sha256Hex(`${tool}:${key}`)}.json`;\n return nexusDataPath('jobs', filename);\n}\n\n/**\n * Resolve a dispatch request to one of three outcomes:\n *\n * - `fresh`: no prior index entry — caller dispatches a new job using the\n * returned `jobId`, then calls `registerIdempotentJob` to record the\n * index entry. The `jobId` is derived deterministically from\n * `(tool, key, inputsHash)` so concurrent dispatches with the same key\n * converge on the same id and don't double-dispatch.\n * - `replay`: an existing entry has the SAME `inputsHash` — caller skips\n * dispatch and returns the existing job's record (via `readJobResult`).\n * - `collision`: an existing entry has a DIFFERENT `inputsHash` — caller\n * fails closed. Reusing a key with different inputs is a programmer\n * error; silent merge would hide bugs.\n *\n * Callers should NOT call `registerIdempotentJob` when this returns\n * `replay` or `collision` — only on `fresh`.\n */\nexport function resolveIdempotency(\n tool: string,\n idempotencyKey: string | undefined,\n inputs: unknown,\n randomFallback: () => string = randomUUID\n): IdempotencyResolution {\n if (idempotencyKey === undefined || idempotencyKey === '') {\n return { kind: 'fresh', jobId: randomFallback() };\n }\n const incomingInputsHash = computeInputsHash(inputs);\n const path = indexFilePathReadOnly(tool, idempotencyKey);\n if (existsSync(path)) {\n const entry = readIndexEntry(path);\n if (entry !== null) {\n if (entry.inputsHash === incomingInputsHash) {\n return { kind: 'replay', jobId: entry.jobId, entry };\n }\n return {\n kind: 'collision',\n existingInputsHash: entry.inputsHash,\n incomingInputsHash,\n existingJobId: entry.jobId,\n };\n }\n // Index file present but unreadable — treat as fresh, log the breach.\n logger.warn('Idempotency index file unreadable; treating as fresh dispatch', { tool, path });\n }\n // Derive jobId deterministically so two concurrent requests with the\n // same (tool, key, inputs) converge on a single id even if both miss\n // the index lookup race.\n const jobId = `job-${tool}-${sha256Hex(`${tool}:${idempotencyKey}:${incomingInputsHash}`).slice(0, 16)}`;\n return { kind: 'fresh', jobId };\n}\n\n/**\n * Persist the index entry after a `fresh` dispatch. Idempotent — if the\n * file already exists (e.g. a concurrent dispatch raced ahead), the\n * existing entry stays in place. Safe to call without checking\n * `existsSync` first.\n */\nexport function registerIdempotentJob(params: {\n tool: string;\n idempotencyKey: string;\n inputs: unknown;\n jobId: string;\n}): void {\n const path = indexFilePath(params.tool, params.idempotencyKey);\n if (existsSync(path)) {\n logger.debug('Idempotency index entry already present; skipping write', {\n tool: params.tool,\n jobId: params.jobId,\n });\n return;\n }\n const entry: IdempotencyIndexEntry = {\n v: 1,\n tool: params.tool,\n key: params.idempotencyKey,\n inputsHash: computeInputsHash(params.inputs),\n jobId: params.jobId,\n createdAt: new Date().toISOString(),\n };\n writeFileSync(path, JSON.stringify(entry, null, 2));\n logger.debug('Wrote idempotency index entry', { tool: params.tool, jobId: params.jobId });\n}\n\n/**\n * Discriminated outcome of `shortCircuitOrFreshJobId` — `continue` means\n * the caller proceeds with dispatch on `jobId`; `shortCircuit` means the\n * caller returns the envelope `value` immediately and skips dispatch.\n */\nexport type ShortCircuitOutcome<TEnvelope> =\n | { readonly kind: 'continue'; readonly jobId: string }\n | { readonly kind: 'shortCircuit'; readonly value: TEnvelope };\n\n/**\n * One-call wrapper around `resolveIdempotency` that lets each dispatch\n * helper stay under the 50-line cap while keeping the shape of the\n * resulting envelope (toolSuccess / toolStructuredError / errorResponse)\n * tool-specific.\n *\n * Caller supplies:\n * - `replayEnvelope(jobId)` — wraps the per-tool \"replay\" envelope. Most\n * tools return a `{ status: 'replay', jobId, pollTool, note }` JSON\n * string via `toolSuccess`.\n * - `collisionEnvelope(existingJobId)` — wraps the error envelope when\n * the same key was reused with different inputs.\n *\n * On `continue`, the caller MUST call `registerIdempotentJob` after\n * writing the pending record so subsequent replays converge.\n */\nexport function shortCircuitOrFreshJobId<TEnvelope>(params: {\n tool: string;\n idempotencyKey: string | undefined;\n inputs: unknown;\n freshJobId: () => string;\n replayEnvelope: (jobId: string) => TEnvelope;\n collisionEnvelope: (existingJobId: string) => TEnvelope;\n}): ShortCircuitOutcome<TEnvelope> {\n const r = resolveIdempotency(\n params.tool,\n params.idempotencyKey,\n params.inputs,\n params.freshJobId\n );\n if (r.kind === 'collision') {\n return { kind: 'shortCircuit', value: params.collisionEnvelope(r.existingJobId) };\n }\n if (r.kind === 'replay') {\n return { kind: 'shortCircuit', value: params.replayEnvelope(r.jobId) };\n }\n return { kind: 'continue', jobId: r.jobId };\n}\n\n/** Read + schema-validate an index file. Returns `null` on miss / corruption. */\nfunction readIndexEntry(path: string): IdempotencyIndexEntry | null {\n try {\n const raw = JSON.parse(readFileSync(path, 'utf-8')) as unknown;\n const parsed = IdempotencyIndexEntrySchema.safeParse(raw);\n if (!parsed.success) {\n logger.warn('Idempotency index file failed schema check', { path });\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn('Idempotency index file read failed', {\n path,\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n","/**\n * Per-tool async-job concurrency cap (#3044 / epic #2631 Stage 3).\n *\n * Tracks in-flight async-mode dispatches in-process so a noisy caller\n * can't queue 1,000 long-running `run_workflow` invocations behind a\n * slow CLI and exhaust adapter slots. The cap is per-tool (each\n * registered tool gets its own slot count) and per-process — restarting\n * the MCP server resets the count, which is fine because the orphan\n * background promises die with it.\n *\n * Configuration order, lowest priority first:\n * 1. The per-tool default in `DEFAULT_JOB_CAPS` below.\n * 2. Environment override `NEXUS_JOB_MAX_CONCURRENT_<TOOL_UPPER>` —\n * tool name is uppercased + `_` for the env-var match. A value of\n * `0` disables async-mode for that tool entirely (`tryAcquire`\n * always returns busy).\n *\n * The Contrarian-vote flag from #3041 specifically asked for the cap\n * to land BEFORE async-mode expands past `orchestrate` (which has a\n * natural ceiling because it's depth-guarded). This module is the\n * primitive that satisfies that ask for `run_workflow` and later tools.\n *\n * @module mcp/jobs/job-concurrency\n */\n\nimport { createLogger } from '../../core/index.js';\n\nconst logger = createLogger({ component: 'job-concurrency' });\n\n/**\n * Default concurrent-job caps per tool. Numbers are starting points\n * informed by typical workload shape, NOT measured ceilings — re-tune\n * after observing actual job duration distributions in #2703 telemetry.\n *\n * `0` would disable async-mode for that tool; absence means \"no cap\"\n * (currently no tool falls into this category).\n */\nexport const DEFAULT_JOB_CAPS: Readonly<Record<string, number>> = {\n orchestrate: 3,\n run_workflow: 3,\n consensus_vote: 2,\n execute_expert: 4,\n // #3726: run_dev_pipeline is a heavy multi-agent pipeline (plan→vote→\n // decompose→implement→qa→security, each a live LLM call). Cap low — 2\n // concurrent real runs already saturate adapter slots on most hosts.\n run_dev_pipeline: 2,\n // #3730: run_pipeline is a multi-stage adaptive orchestrator with per-stage\n // experts (live LLM calls). Same shape as run_dev_pipeline — cap low at 2.\n run_pipeline: 2,\n // #3731: pr_review fans out to 5 live LLM voters in parallel. Same heavy\n // multi-llm-panel shape as consensus_vote — cap low at 2.\n pr_review: 2,\n // #3731: supply_chain_tradeoff_panel fans out to up to 7 live LLM voters in\n // parallel. Same heavy multi-llm-panel shape as consensus_vote — cap low at 2.\n supply_chain_tradeoff_panel: 2,\n // #3732: execute_spec runs a full spec DAG pipeline (parse→decompose→compile\n // →execute→validate→analyze, live multi-agent execution). Heavy — cap low at 2.\n execute_spec: 2,\n // #3732: run_graph_workflow runs up to ~100 expert nodes with checkpoints.\n // Heavy multi-node pipeline — cap low at 2.\n run_graph_workflow: 2,\n // #3732: run (execute:true) dispatches the heaviest engines (dev-pipeline/\n // pipeline) via the MetaDispatcher. Same heavy-pipeline shape — cap low at 2.\n run: 2,\n};\n\n/**\n * Default total cross-tool cap (defensive backstop, #3046 Stage 5).\n * Per-tool caps prevent a noisy single tool; the global cap prevents\n * 5 tools × 3 jobs each from saturating the host's adapter slots.\n *\n * Env override: `NEXUS_JOB_MAX_CONCURRENT_TOTAL`. Defaults to 10 —\n * comfortably above the sum of per-tool defaults (3+3+2+4=12 is also\n * fine because no realistic workload fills every tool simultaneously)\n * but stops runaway parallel fan-outs.\n */\nexport const DEFAULT_GLOBAL_JOB_CAP = 10;\n\n/** In-flight count per tool. Reset on process restart. */\nconst inFlight = new Map<string, number>();\n\n/** Returns the configured per-tool cap — env override beats default. */\nexport function getJobCap(toolName: string): number {\n const envKey = `NEXUS_JOB_MAX_CONCURRENT_${toolName.toUpperCase()}`;\n const envValue = process.env[envKey];\n if (envValue !== undefined && envValue !== '') {\n const parsed = Number(envValue);\n if (Number.isInteger(parsed) && parsed >= 0) {\n return parsed;\n }\n logger.warn('Invalid env override for job cap — ignoring', {\n tool: toolName,\n envKey,\n envValue,\n });\n }\n return DEFAULT_JOB_CAPS[toolName] ?? DEFAULT_GLOBAL_JOB_CAP;\n}\n\n/**\n * Returns the global cross-tool cap (#3046 Stage 5). Env override:\n * `NEXUS_JOB_MAX_CONCURRENT_TOTAL`. A value of `0` disables async-mode\n * across ALL tools simultaneously.\n */\nexport function getGlobalJobCap(): number {\n const envValue = process.env['NEXUS_JOB_MAX_CONCURRENT_TOTAL'];\n if (envValue !== undefined && envValue !== '') {\n const parsed = Number(envValue);\n if (Number.isInteger(parsed) && parsed >= 0) {\n return parsed;\n }\n logger.warn('Invalid env override for global job cap — ignoring', {\n envKey: 'NEXUS_JOB_MAX_CONCURRENT_TOTAL',\n envValue,\n });\n }\n return DEFAULT_GLOBAL_JOB_CAP;\n}\n\n/** Sum of in-flight counts across all tools (Stage 5 observability). */\nexport function getTotalInFlight(): number {\n let total = 0;\n for (const count of inFlight.values()) total += count;\n return total;\n}\n\n/** Current in-flight count for a tool (testing + observability helper). */\nexport function getInFlight(toolName: string): number {\n return inFlight.get(toolName) ?? 0;\n}\n\n/**\n * Attempt to acquire one slot. Returns `true` on success (caller MUST\n * `release()` exactly once when the job finishes / fails). Returns\n * `false` when EITHER cap is full — per-tool cap OR cross-tool global\n * cap (#3046 Stage 5). Caller responds synchronously with the busy\n * envelope (`{ status: 'busy', retryAfterMs }`).\n *\n * Atomicity note: Node.js is single-threaded between awaits, so this\n * read-then-write pattern is safe as long as no `await` interleaves\n * — and it doesn't here.\n */\nexport function tryAcquire(toolName: string): boolean {\n const cap = getJobCap(toolName);\n // Cap of 0 disables async-mode for the tool.\n if (cap === 0) return false;\n const current = inFlight.get(toolName) ?? 0;\n if (current >= cap) return false;\n // #3046 Stage 5: global cap check. Prevents 5 tools × 3 jobs each\n // saturating adapter slots even when each per-tool cap is satisfied.\n const globalCap = getGlobalJobCap();\n if (globalCap === 0) return false;\n if (getTotalInFlight() >= globalCap) return false;\n inFlight.set(toolName, current + 1);\n return true;\n}\n\n/**\n * Release one slot. Idempotent only in the trivial sense (calling twice\n * is a bug — the counter would underflow). Callers should pair every\n * `tryAcquire` returning `true` with exactly one `release` in a\n * `finally` block to be safe on both success and rejection paths.\n */\nexport function release(toolName: string): void {\n const current = inFlight.get(toolName) ?? 0;\n if (current === 0) {\n logger.warn('release() called with no in-flight count — caller bug', { tool: toolName });\n return;\n }\n inFlight.set(toolName, current - 1);\n}\n\n/**\n * Suggested retry interval for a busy response. Linear in current\n * load — at full cap, suggest 30s; halved as load shrinks. Pure\n * convenience for clients implementing exponential backoff.\n */\nexport function suggestRetryAfterMs(toolName: string): number {\n const cap = getJobCap(toolName);\n if (cap === 0) return 0; // never retry — async-mode is disabled\n const current = inFlight.get(toolName) ?? 0;\n // 30s base, scaled by fullness (clamped to [5s, 60s]).\n const base = 30_000 * (current / Math.max(1, cap));\n return Math.min(60_000, Math.max(5_000, base));\n}\n\n/** Reset all counters. Test-only — do not call from production code. */\nexport function _resetForTests(): void {\n inFlight.clear();\n}\n","/**\n * Shared async-job dispatcher — `runAsJob` (#3729 / epic #2631).\n *\n * Three tools (orchestrate, run_workflow, consensus_vote) implemented the\n * async-mode dispatcher VERBATIM: resolve idempotency → tryAcquire (busy\n * envelope on cap) → writeJobPending → registerIdempotentJob → fire a\n * detached background `run` that writes complete/failed + releases the slot\n * in a `finally` → return a synchronous `{ status: 'pending', jobId }`\n * envelope. This module extracts that sequence once so new long-running\n * tools (run_dev_pipeline, run_pipeline, …) opt into async with a few lines.\n *\n * The dispatcher sequence is FIXED here; the only per-tool variation is the\n * envelope shape (some tools use `ToolResult` via toolSuccess/\n * toolStructuredError, run_workflow uses its structurally-identical\n * `ToolResponse`). Callers that need a non-default envelope supply\n * `toEnvelope`; the default builders reproduce the orchestrate/consensus_vote\n * `ToolResult` envelopes byte-for-byte so faithful migration is a drop-in.\n *\n * @module mcp/jobs/run-as-job\n */\n\nimport type { ILogger } from '../../core/index.js';\nimport { toolSuccess, toolStructuredError, type ToolResult } from '../tools/tool-result.js';\nimport { writeJobComplete, writeJobFailed, writeJobPending } from './job-result-store.js';\nimport { registerIdempotentJob, shortCircuitOrFreshJobId } from './job-idempotency.js';\nimport { release, suggestRetryAfterMs, tryAcquire } from './job-concurrency.js';\nimport { resolveClassGuardMs } from '../../config/timeouts.js';\n\n/**\n * Async-job-body runaway-guard (#3734). A backgrounded job body has NO MCP\n * request timeout (that is the point of async mode), so without a ceiling a\n * wedged `run` would hold its concurrency slot and pending record forever.\n * The `async-job-body` operation class (3600s, honoring NEXUS_TIMEOUT_MULTIPLIER\n * + the per-class override) bounds it. On expiry the job is recorded as failed\n * with `runaway guard exceeded` and the slot is released by the existing\n * `finally`. This is a runaway-guard, not an SLA — 1h is generous.\n */\nexport const ASYNC_JOB_BODY_GUARD_CLASS = 'async-job-body' as const;\n\n/**\n * Fraction of the async-job-body guard at which a near-timeout WARN is emitted\n * before the guard fires. Lower than the generic 0.8 so operators see a wedged\n * long-running job well before the (very high) ceiling trips.\n */\nexport const ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD = 0.5;\n\n/** Sentinel rejection used to distinguish a guard expiry from a body failure. */\nconst ASYNC_JOB_BODY_RUNAWAY_MESSAGE = 'runaway guard exceeded';\n\ninterface GuardHandles {\n /** Resolves only when the guard window elapses (never resolves on clear). */\n readonly expired: Promise<never>;\n /** Cancels the guard + near-timeout timers. */\n readonly clear: () => void;\n}\n\n/**\n * Builds a guard that rejects with the runaway sentinel after `guardMs`, and\n * emits a one-shot near-timeout WARN at {@link ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD}.\n */\nfunction makeAsyncBodyGuard(\n jobId: string,\n toolName: string,\n guardMs: number,\n logger: ILogger | undefined\n): GuardHandles {\n let guardTimer: ReturnType<typeof setTimeout> | undefined;\n let warnTimer: ReturnType<typeof setTimeout> | undefined;\n const expired = new Promise<never>((_resolve, reject) => {\n warnTimer = setTimeout(\n () => {\n logger?.warn(`Async ${toolName} job approaching runaway guard`, {\n jobId,\n guardMs,\n thresholdFraction: ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD,\n });\n },\n Math.floor(guardMs * ASYNC_JOB_BODY_NEAR_TIMEOUT_THRESHOLD)\n );\n guardTimer = setTimeout(() => {\n reject(new Error(ASYNC_JOB_BODY_RUNAWAY_MESSAGE));\n }, guardMs);\n // Don't keep the event loop alive solely for these timers.\n guardTimer.unref();\n warnTimer.unref();\n });\n return {\n expired,\n clear: () => {\n if (guardTimer !== undefined) clearTimeout(guardTimer);\n if (warnTimer !== undefined) clearTimeout(warnTimer);\n },\n };\n}\n\n/**\n * Per-tool envelope builders. Every async dispatcher returns the same five\n * logical outcomes; only their wire shape differs. Supplying this lets a tool\n * that uses a different success/error factory (e.g. run_workflow's\n * `successResponse`/`errorResponse`) reuse the dispatcher unchanged.\n *\n * @template E - The tool's MCP envelope type (defaults to {@link ToolResult}).\n */\nexport interface JobEnvelopeBuilders<E> {\n /** `{ status: 'pending', jobId, pollTool, note }` — returned synchronously after dispatch. */\n readonly pending: (jobId: string) => E;\n /** `{ status: 'busy', retryAfterMs, note }` — concurrency cap reached. */\n readonly busy: (retryAfterMs: number, toolName: string) => E;\n /** `{ status: 'replay', jobId, pollTool, note }` — idempotency key matched a prior dispatch. */\n readonly replay: (jobId: string) => E;\n /** Error envelope — idempotency key reused with different inputs. */\n readonly collision: (existingJobId: string) => E;\n}\n\n/** Default pending envelope (orchestrate/consensus_vote shape). */\nexport function defaultPendingEnvelope(jobId: string): ToolResult {\n return toolSuccess(\n JSON.stringify({\n status: 'pending',\n jobId,\n pollTool: 'get_job_result',\n note: 'Poll via get_job_result({ jobId }) until status !== \"pending\".',\n })\n );\n}\n\n/** Default busy envelope (orchestrate/consensus_vote shape). */\nexport function defaultBusyEnvelope(retryAfterMs: number, toolName: string): ToolResult {\n return toolSuccess(\n JSON.stringify({\n status: 'busy',\n retryAfterMs,\n note: `Async-mode concurrency cap reached for ${toolName}. Retry later or use mode: \"sync\".`,\n })\n );\n}\n\n/** Default replay envelope (orchestrate/consensus_vote shape). */\nexport function defaultReplayEnvelope(jobId: string): ToolResult {\n return toolSuccess(\n JSON.stringify({\n status: 'replay',\n jobId,\n pollTool: 'get_job_result',\n note: 'Idempotency key matched a prior dispatch — poll get_job_result for current status.',\n })\n );\n}\n\n/** Default collision envelope (orchestrate/consensus_vote shape). */\nexport function defaultCollisionEnvelope(existingJobId: string): ToolResult {\n return toolStructuredError({\n errorCategory: 'validation',\n message: `Idempotency key already used with different inputs. Existing jobId: ${existingJobId}. Use a fresh key or omit it.`,\n });\n}\n\n/** The full default ({@link ToolResult}) envelope set. */\nexport const DEFAULT_JOB_ENVELOPES: JobEnvelopeBuilders<ToolResult> = {\n pending: defaultPendingEnvelope,\n busy: defaultBusyEnvelope,\n replay: defaultReplayEnvelope,\n collision: defaultCollisionEnvelope,\n};\n\n/**\n * Parameters for {@link runAsJob}.\n *\n * @template I - The tool's validated input type (hashed for idempotency,\n * passed to `run`).\n * @template R - The structured result `run` resolves to; recorded verbatim\n * via `writeJobComplete` and returned by a later `get_job_result(jobId)`.\n * @template E - The tool's envelope type (defaults to {@link ToolResult}).\n */\nexport interface RunAsJobParams<I, R, E = ToolResult> {\n /** MCP tool name — the idempotency / concurrency / job-store key. */\n readonly toolName: string;\n /** Validated tool input. Hashed for idempotency + passed to `run`. */\n readonly input: I;\n /** Caller-supplied idempotency key (optional). */\n readonly idempotencyKey?: string | undefined;\n /** Mints a fresh jobId when no idempotency short-circuit applies. */\n readonly freshJobId: () => string;\n /**\n * The detached background work. Receives the resolved `jobId` (so the\n * runner can thread it into a task-state log) and the `input`. Its\n * resolved value is recorded as the job's `complete` result; a rejection\n * is recorded as `failed`.\n */\n readonly run: (jobId: string, input: I) => Promise<R>;\n /** Per-tool envelope builders. Defaults to the {@link ToolResult} set. */\n readonly toEnvelope?: JobEnvelopeBuilders<E>;\n /** Optional logger for the background failure path. */\n readonly logger?: ILogger | undefined;\n}\n\n/**\n * Dispatch `run` as a detached background job and return a synchronous\n * envelope. Performs the EXACT sequence the three hand-rolled dispatchers\n * shared:\n *\n * 1. Resolve idempotency BEFORE acquiring a slot — a replay/collision must\n * not burn capacity a live caller could use.\n * 2. `tryAcquire(toolName)` — over-cap returns the `busy` envelope.\n * 3. `writeJobPending` + `registerIdempotentJob` (when a key was supplied).\n * 4. Fire-and-forget `run(jobId, input)`: on resolve `writeJobComplete`,\n * on reject `writeJobFailed`, `release` in a `finally`.\n * 5. Return the `pending` envelope (`{ status: 'pending', jobId, … }`).\n *\n * The background promise is intentionally not awaited — async mode exists\n * precisely because awaiting it would defeat the contract. Its rejection is\n * caught + recorded; nothing escapes unhandled.\n *\n * @returns The synchronous envelope: `pending` on dispatch, `busy` on cap,\n * `replay`/`collision` on an idempotency match.\n */\nexport function runAsJob<I, R, E = ToolResult>(params: RunAsJobParams<I, R, E>): E {\n const env = params.toEnvelope ?? (DEFAULT_JOB_ENVELOPES as unknown as JobEnvelopeBuilders<E>);\n\n // Step 1: idempotency resolves BEFORE the slot acquire.\n const idempotency = shortCircuitOrFreshJobId<E>({\n tool: params.toolName,\n idempotencyKey: params.idempotencyKey,\n inputs: params.input,\n freshJobId: params.freshJobId,\n replayEnvelope: env.replay,\n collisionEnvelope: env.collision,\n });\n if (idempotency.kind === 'shortCircuit') return idempotency.value;\n\n // Step 2: per-tool concurrency cap. Over-cap returns busy synchronously.\n if (!tryAcquire(params.toolName)) {\n return env.busy(suggestRetryAfterMs(params.toolName), params.toolName);\n }\n\n const jobId = idempotency.jobId;\n // Step 3: pending record + idempotency index entry.\n writeJobPending(jobId, params.toolName);\n if (params.idempotencyKey !== undefined && params.idempotencyKey !== '') {\n registerIdempotentJob({\n tool: params.toolName,\n idempotencyKey: params.idempotencyKey,\n inputs: params.input,\n jobId,\n });\n }\n\n // Step 4: detached background run with terminal recording + slot release.\n void runJobInBackground(jobId, params);\n\n // Step 5: synchronous pending envelope.\n return env.pending(jobId);\n}\n\n/**\n * Fire-and-forget background runner. Exported (awaitable) so integration\n * tests can drive the dispatch deterministically instead of racing the\n * detached promise.\n * @internal\n */\nexport async function runJobInBackground<I, R, E>(\n jobId: string,\n params: RunAsJobParams<I, R, E>\n): Promise<void> {\n const guardMs = resolveClassGuardMs(ASYNC_JOB_BODY_GUARD_CLASS);\n const guard = makeAsyncBodyGuard(jobId, params.toolName, guardMs, params.logger);\n try {\n // Race the body against the runaway-guard. On guard expiry the guard\n // rejects with the sentinel → recorded as failed below. On body settle the\n // guard is cleared so it can never fire afterward.\n const result = await Promise.race([params.run(jobId, params.input), guard.expired]);\n writeJobComplete(jobId, params.toolName, result);\n } catch (err: unknown) {\n const errObj = err instanceof Error ? err : new Error(String(err));\n params.logger?.error(`Async ${params.toolName} dispatch failed`, errObj, { jobId });\n writeJobFailed(jobId, params.toolName, errObj.message);\n } finally {\n guard.clear();\n release(params.toolName);\n }\n}\n"],"mappings":"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","names":["z","logger","logger","logger","z","z","z","z","z","logger","err","logger","logger","logger","logger","z","logger","z","logger","z","z","appendFileSync","readFileSync","writeFileSync","existsSync","logger","existsSync","readFileSync","writeFileSync","appendFileSync","logger","logger","logger","existsSync","readFileSync","writeFileSync","z","logger","z","existsSync","writeFileSync","readFileSync","err","existsSync","readFileSync","writeFileSync","z","logger","z","existsSync","writeFileSync","readFileSync","err","logger","logger","logger","err","randomUUID","logger","z"]}
|