nexus-agents 9.0.2 → 9.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/{ast-rule-runner-IROJO2LR.js → ast-rule-runner-GW3RRDDN.js} +3 -3
  2. package/dist/{child-mcp-config-SOEVU3N4.js → child-mcp-config-AX5LNK2U.js} +2 -2
  3. package/dist/{chunk-VL5XUWRA.js → chunk-2JUGZWTJ.js} +2 -2
  4. package/dist/{chunk-HABRCWMK.js → chunk-2OHARKQS.js} +3 -3
  5. package/dist/{chunk-7JYW5F77.js → chunk-3A24GW2T.js} +5 -5
  6. package/dist/{chunk-NRB6TOUO.js → chunk-3NYZ5HZA.js} +4 -4
  7. package/dist/{chunk-L25VW7RC.js → chunk-6PKIUOWP.js} +13 -13
  8. package/dist/{chunk-WQCYMWMF.js → chunk-7TBDUW7E.js} +4 -4
  9. package/dist/{chunk-FSM6ZCVF.js → chunk-7TLUEWRK.js} +3 -3
  10. package/dist/{chunk-EF5FB4QM.js → chunk-A2UFTOL3.js} +4 -4
  11. package/dist/{chunk-FBJ6D2GF.js → chunk-CYWZ7W2C.js} +2 -2
  12. package/dist/{chunk-DIM3YNH4.js → chunk-FJ35WCE4.js} +7 -7
  13. package/dist/{chunk-T5IBXFFY.js → chunk-HK5DNXNV.js} +5 -5
  14. package/dist/{chunk-3OBOVCFZ.js → chunk-IIOXL76E.js} +3 -3
  15. package/dist/{chunk-3OBOVCFZ.js.map → chunk-IIOXL76E.js.map} +1 -1
  16. package/dist/{chunk-GZHDEMLN.js → chunk-JU4YPMVT.js} +197 -98
  17. package/dist/chunk-JU4YPMVT.js.map +1 -0
  18. package/dist/{chunk-LM7NMCEE.js → chunk-KSIHEDDG.js} +2 -2
  19. package/dist/{chunk-WNVJQ5SC.js → chunk-KSZAEQAZ.js} +4 -4
  20. package/dist/{chunk-MGVYGV7P.js → chunk-MW454P5G.js} +17 -13
  21. package/dist/chunk-MW454P5G.js.map +1 -0
  22. package/dist/{chunk-HX2L3RU2.js → chunk-N2BSUYFL.js} +2 -2
  23. package/dist/{chunk-DQ4PJVOC.js → chunk-NACIKSZF.js} +5 -5
  24. package/dist/{chunk-KSY5LNO5.js → chunk-POI3L46U.js} +2 -2
  25. package/dist/{chunk-XEDWWMZ3.js → chunk-PQWFZWDL.js} +2 -2
  26. package/dist/{chunk-7ZZHQ6H3.js → chunk-QXBOILNV.js} +2 -2
  27. package/dist/{chunk-C5P5D45H.js → chunk-RDZ42Z3Q.js} +3 -3
  28. package/dist/{chunk-AJ37AWCG.js → chunk-SAK2PAQD.js} +2 -2
  29. package/dist/{chunk-MPAAWIDI.js → chunk-TMCE755U.js} +2 -2
  30. package/dist/{chunk-GTYGMOMW.js → chunk-TQJRQ3MR.js} +5 -5
  31. package/dist/{chunk-NHNXANOF.js → chunk-TVUPVQXD.js} +7 -7
  32. package/dist/{chunk-4E72H7XZ.js → chunk-XA5JF2QZ.js} +2 -2
  33. package/dist/{chunk-SB3NEYNN.js → chunk-XMXU7EA7.js} +2 -2
  34. package/dist/{chunk-SFILA57C.js → chunk-XSNFBUX3.js} +44 -42
  35. package/dist/{chunk-SFILA57C.js.map → chunk-XSNFBUX3.js.map} +1 -1
  36. package/dist/{chunk-FVYQWWPB.js → chunk-Y2W44LHI.js} +5 -5
  37. package/dist/{chunk-D26ZNDI3.js → chunk-YCDDSJ6L.js} +2 -2
  38. package/dist/{chunk-PYDOAA3J.js → chunk-YK6MGGPV.js} +2 -2
  39. package/dist/{chunk-V362YGAV.js → chunk-Z5CLWX4M.js} +6 -5
  40. package/dist/{chunk-PF2TM7CW.js → chunk-Z6LCG3ZM.js} +2 -2
  41. package/dist/{chunk-LLDIASHH.js → chunk-ZZ63WG24.js} +3 -3
  42. package/dist/{cli-circuit-breaker-CL333R6G.js → cli-circuit-breaker-QDMRHG5K.js} +3 -3
  43. package/dist/{cli-readiness-G3YIRQE7.js → cli-readiness-7YQ7S2AY.js} +7 -7
  44. package/dist/cli.d.ts +1 -1
  45. package/dist/cli.js +44 -44
  46. package/dist/{composite-router-WRLV4FGT.js → composite-router-KWVZJE5J.js} +2 -2
  47. package/dist/{consensus-vote-THWFSBC7.js → consensus-vote-YDKECHPF.js} +17 -17
  48. package/dist/{consensus-vote-types-D2RbRYve.d.ts → consensus-vote-types-DA_y5jja.d.ts} +13 -5
  49. package/dist/{context-retriever-SNYHJYBW.js → context-retriever-XOT3JESN.js} +8 -8
  50. package/dist/{doctor-deep-Y7V22EON.js → doctor-deep-L5MCQ4RP.js} +3 -3
  51. package/dist/{doctor-gateway-report-AGFLKDJD.js → doctor-gateway-report-4B6KE7B5.js} +7 -7
  52. package/dist/{doctor-live-GVW7URQE.js → doctor-live-77X66SFV.js} +11 -11
  53. package/dist/{expert-bridge-JEZYYPHE.js → expert-bridge-S4LEWNOQ.js} +4 -4
  54. package/dist/{factory-XANTK76M.js → factory-U35CCT3I.js} +5 -5
  55. package/dist/{factory-YPM27Q4H.js → factory-WHP7VBCY.js} +10 -10
  56. package/dist/{improvement-review-FQRJMLHU.js → improvement-review-CYK3E2J6.js} +6 -6
  57. package/dist/index.d.ts +7 -5
  58. package/dist/index.js +32 -32
  59. package/dist/{init-opencode-H2EKCKD2.js → init-opencode-OTTNZHKO.js} +6 -6
  60. package/dist/{issue-triage-2ONLBRFO.js → issue-triage-WRNKM4W7.js} +6 -6
  61. package/dist/{model-config-helpers-L5QFCKPC.js → model-config-helpers-URTK3TDT.js} +2 -2
  62. package/dist/{openai-compat-adapter-B2D7SS3W.js → openai-compat-adapter-CCYSADQL.js} +6 -6
  63. package/dist/{outcome-store-adapter-VZ3GSHAC.js → outcome-store-adapter-GAT6LFFD.js} +2 -2
  64. package/dist/{pr-reviewer-helpers-TBYZRGYD.js → pr-reviewer-helpers-ECI3O755.js} +4 -4
  65. package/dist/{registry-command-5PJYDUEV.js → registry-command-ZNS2WFJ5.js} +2 -2
  66. package/dist/{repo-security-plan-Q4DPMXMI.js → repo-security-plan-FE7BKQH5.js} +3 -3
  67. package/dist/{research-helpers-synthesize-JCZ4J4FU.js → research-helpers-synthesize-ECSX4ZO2.js} +4 -4
  68. package/dist/{routing-memory-JQEYHJNM.js → routing-memory-5CW56QBY.js} +2 -2
  69. package/dist/{session-memory-ZIU2KLYZ.js → session-memory-VQB3KEOW.js} +3 -3
  70. package/dist/{setup-config-SFPGFQTG.js → setup-config-3WWCV7RF.js} +3 -3
  71. package/dist/{setup-custom-api-QXF5XLKP.js → setup-custom-api-6QJS7YUQ.js} +3 -3
  72. package/dist/setup-data-dir-4J6XKGDH.js +36 -0
  73. package/dist/{tool-memory-WTOTIEHV.js → tool-memory-J7HO5C7H.js} +5 -5
  74. package/dist/{unified-registry-2FWLKUKQ.js → unified-registry-JIWD7D4S.js} +11 -11
  75. package/dist/{weather-report-HVBREECQ.js → weather-report-GSZVNNE2.js} +2 -2
  76. package/package.json +1 -1
  77. package/dist/chunk-GZHDEMLN.js.map +0 -1
  78. package/dist/chunk-MGVYGV7P.js.map +0 -1
  79. package/dist/setup-data-dir-XCHPJFBD.js +0 -36
  80. /package/dist/{ast-rule-runner-IROJO2LR.js.map → ast-rule-runner-GW3RRDDN.js.map} +0 -0
  81. /package/dist/{child-mcp-config-SOEVU3N4.js.map → child-mcp-config-AX5LNK2U.js.map} +0 -0
  82. /package/dist/{chunk-VL5XUWRA.js.map → chunk-2JUGZWTJ.js.map} +0 -0
  83. /package/dist/{chunk-HABRCWMK.js.map → chunk-2OHARKQS.js.map} +0 -0
  84. /package/dist/{chunk-7JYW5F77.js.map → chunk-3A24GW2T.js.map} +0 -0
  85. /package/dist/{chunk-NRB6TOUO.js.map → chunk-3NYZ5HZA.js.map} +0 -0
  86. /package/dist/{chunk-L25VW7RC.js.map → chunk-6PKIUOWP.js.map} +0 -0
  87. /package/dist/{chunk-WQCYMWMF.js.map → chunk-7TBDUW7E.js.map} +0 -0
  88. /package/dist/{chunk-FSM6ZCVF.js.map → chunk-7TLUEWRK.js.map} +0 -0
  89. /package/dist/{chunk-EF5FB4QM.js.map → chunk-A2UFTOL3.js.map} +0 -0
  90. /package/dist/{chunk-FBJ6D2GF.js.map → chunk-CYWZ7W2C.js.map} +0 -0
  91. /package/dist/{chunk-DIM3YNH4.js.map → chunk-FJ35WCE4.js.map} +0 -0
  92. /package/dist/{chunk-T5IBXFFY.js.map → chunk-HK5DNXNV.js.map} +0 -0
  93. /package/dist/{chunk-LM7NMCEE.js.map → chunk-KSIHEDDG.js.map} +0 -0
  94. /package/dist/{chunk-WNVJQ5SC.js.map → chunk-KSZAEQAZ.js.map} +0 -0
  95. /package/dist/{chunk-HX2L3RU2.js.map → chunk-N2BSUYFL.js.map} +0 -0
  96. /package/dist/{chunk-DQ4PJVOC.js.map → chunk-NACIKSZF.js.map} +0 -0
  97. /package/dist/{chunk-KSY5LNO5.js.map → chunk-POI3L46U.js.map} +0 -0
  98. /package/dist/{chunk-XEDWWMZ3.js.map → chunk-PQWFZWDL.js.map} +0 -0
  99. /package/dist/{chunk-7ZZHQ6H3.js.map → chunk-QXBOILNV.js.map} +0 -0
  100. /package/dist/{chunk-C5P5D45H.js.map → chunk-RDZ42Z3Q.js.map} +0 -0
  101. /package/dist/{chunk-AJ37AWCG.js.map → chunk-SAK2PAQD.js.map} +0 -0
  102. /package/dist/{chunk-MPAAWIDI.js.map → chunk-TMCE755U.js.map} +0 -0
  103. /package/dist/{chunk-GTYGMOMW.js.map → chunk-TQJRQ3MR.js.map} +0 -0
  104. /package/dist/{chunk-NHNXANOF.js.map → chunk-TVUPVQXD.js.map} +0 -0
  105. /package/dist/{chunk-4E72H7XZ.js.map → chunk-XA5JF2QZ.js.map} +0 -0
  106. /package/dist/{chunk-SB3NEYNN.js.map → chunk-XMXU7EA7.js.map} +0 -0
  107. /package/dist/{chunk-FVYQWWPB.js.map → chunk-Y2W44LHI.js.map} +0 -0
  108. /package/dist/{chunk-D26ZNDI3.js.map → chunk-YCDDSJ6L.js.map} +0 -0
  109. /package/dist/{chunk-PYDOAA3J.js.map → chunk-YK6MGGPV.js.map} +0 -0
  110. /package/dist/{chunk-V362YGAV.js.map → chunk-Z5CLWX4M.js.map} +0 -0
  111. /package/dist/{chunk-PF2TM7CW.js.map → chunk-Z6LCG3ZM.js.map} +0 -0
  112. /package/dist/{chunk-LLDIASHH.js.map → chunk-ZZ63WG24.js.map} +0 -0
  113. /package/dist/{cli-circuit-breaker-CL333R6G.js.map → cli-circuit-breaker-QDMRHG5K.js.map} +0 -0
  114. /package/dist/{cli-readiness-G3YIRQE7.js.map → cli-readiness-7YQ7S2AY.js.map} +0 -0
  115. /package/dist/{composite-router-WRLV4FGT.js.map → composite-router-KWVZJE5J.js.map} +0 -0
  116. /package/dist/{consensus-vote-THWFSBC7.js.map → consensus-vote-YDKECHPF.js.map} +0 -0
  117. /package/dist/{context-retriever-SNYHJYBW.js.map → context-retriever-XOT3JESN.js.map} +0 -0
  118. /package/dist/{doctor-deep-Y7V22EON.js.map → doctor-deep-L5MCQ4RP.js.map} +0 -0
  119. /package/dist/{doctor-gateway-report-AGFLKDJD.js.map → doctor-gateway-report-4B6KE7B5.js.map} +0 -0
  120. /package/dist/{doctor-live-GVW7URQE.js.map → doctor-live-77X66SFV.js.map} +0 -0
  121. /package/dist/{expert-bridge-JEZYYPHE.js.map → expert-bridge-S4LEWNOQ.js.map} +0 -0
  122. /package/dist/{factory-XANTK76M.js.map → factory-U35CCT3I.js.map} +0 -0
  123. /package/dist/{factory-YPM27Q4H.js.map → factory-WHP7VBCY.js.map} +0 -0
  124. /package/dist/{improvement-review-FQRJMLHU.js.map → improvement-review-CYK3E2J6.js.map} +0 -0
  125. /package/dist/{init-opencode-H2EKCKD2.js.map → init-opencode-OTTNZHKO.js.map} +0 -0
  126. /package/dist/{issue-triage-2ONLBRFO.js.map → issue-triage-WRNKM4W7.js.map} +0 -0
  127. /package/dist/{model-config-helpers-L5QFCKPC.js.map → model-config-helpers-URTK3TDT.js.map} +0 -0
  128. /package/dist/{openai-compat-adapter-B2D7SS3W.js.map → openai-compat-adapter-CCYSADQL.js.map} +0 -0
  129. /package/dist/{outcome-store-adapter-VZ3GSHAC.js.map → outcome-store-adapter-GAT6LFFD.js.map} +0 -0
  130. /package/dist/{pr-reviewer-helpers-TBYZRGYD.js.map → pr-reviewer-helpers-ECI3O755.js.map} +0 -0
  131. /package/dist/{registry-command-5PJYDUEV.js.map → registry-command-ZNS2WFJ5.js.map} +0 -0
  132. /package/dist/{repo-security-plan-Q4DPMXMI.js.map → repo-security-plan-FE7BKQH5.js.map} +0 -0
  133. /package/dist/{research-helpers-synthesize-JCZ4J4FU.js.map → research-helpers-synthesize-ECSX4ZO2.js.map} +0 -0
  134. /package/dist/{routing-memory-JQEYHJNM.js.map → routing-memory-5CW56QBY.js.map} +0 -0
  135. /package/dist/{session-memory-ZIU2KLYZ.js.map → session-memory-VQB3KEOW.js.map} +0 -0
  136. /package/dist/{setup-config-SFPGFQTG.js.map → setup-config-3WWCV7RF.js.map} +0 -0
  137. /package/dist/{setup-custom-api-QXF5XLKP.js.map → setup-custom-api-6QJS7YUQ.js.map} +0 -0
  138. /package/dist/{setup-data-dir-XCHPJFBD.js.map → setup-data-dir-4J6XKGDH.js.map} +0 -0
  139. /package/dist/{tool-memory-WTOTIEHV.js.map → tool-memory-J7HO5C7H.js.map} +0 -0
  140. /package/dist/{unified-registry-2FWLKUKQ.js.map → unified-registry-JIWD7D4S.js.map} +0 -0
  141. /package/dist/{weather-report-HVBREECQ.js.map → weather-report-GSZVNNE2.js.map} +0 -0
@@ -21,24 +21,24 @@ import {
21
21
  toolSuccess,
22
22
  withProgressHeartbeat,
23
23
  wrapToolWithTimeout
24
- } from "./chunk-EF5FB4QM.js";
24
+ } from "./chunk-A2UFTOL3.js";
25
25
  import {
26
26
  getToolMemory
27
- } from "./chunk-WNVJQ5SC.js";
27
+ } from "./chunk-KSZAEQAZ.js";
28
28
  import {
29
29
  allOf
30
30
  } from "./chunk-EZNIYU5T.js";
31
31
  import {
32
32
  VERSION
33
- } from "./chunk-FSM6ZCVF.js";
33
+ } from "./chunk-7TLUEWRK.js";
34
34
  import {
35
35
  isGatewayModelAdapter
36
- } from "./chunk-T5IBXFFY.js";
36
+ } from "./chunk-HK5DNXNV.js";
37
37
  import {
38
38
  ModelBoundAdapter,
39
39
  createEvent,
40
40
  getGlobalRegistry
41
- } from "./chunk-7JYW5F77.js";
41
+ } from "./chunk-3A24GW2T.js";
42
42
  import {
43
43
  UNVERIFIABLE_STDERR_RE,
44
44
  classifyUnverifiable,
@@ -46,24 +46,25 @@ import {
46
46
  getAvailableClis,
47
47
  isAbsentSeat,
48
48
  markUnverifiable
49
- } from "./chunk-MGVYGV7P.js";
49
+ } from "./chunk-MW454P5G.js";
50
50
  import {
51
51
  ensureGatewayDiscovered
52
- } from "./chunk-LLDIASHH.js";
52
+ } from "./chunk-ZZ63WG24.js";
53
53
  import {
54
+ CLI_TO_MODELSDEV_VENDOR,
54
55
  delay,
55
56
  getAbortObservation,
56
57
  sleep,
57
58
  withTimeout
58
- } from "./chunk-V362YGAV.js";
59
+ } from "./chunk-Z5CLWX4M.js";
59
60
  import {
60
61
  getDefaultCliCircuitBreakerRegistry
61
- } from "./chunk-MPAAWIDI.js";
62
+ } from "./chunk-TMCE755U.js";
62
63
  import {
63
64
  sanitizeErrorDetails,
64
65
  sanitizeOutput,
65
66
  sanitizeStringLeaves
66
- } from "./chunk-AJ37AWCG.js";
67
+ } from "./chunk-SAK2PAQD.js";
67
68
  import {
68
69
  AgentError,
69
70
  DecisionCostStore,
@@ -95,6 +96,7 @@ import {
95
96
  getPipelineEventBus,
96
97
  getRandomProvider,
97
98
  getTimeProvider,
99
+ hasGatewaySlotCatalog,
98
100
  isAuthFailureText,
99
101
  isCallerAbortError,
100
102
  isCliName,
@@ -112,13 +114,14 @@ import {
112
114
  readVoteRecords,
113
115
  recordUsageEvent,
114
116
  registerPersistentOutcomeStoreFactory,
117
+ resolveGatewayDefault,
115
118
  resolveInsideRoot,
116
119
  resolveModelIdentitySync,
117
120
  resolveVoteRecordsPath,
118
121
  servedCostDetail,
119
122
  stepBus,
120
123
  voteRecordWriteFailedMessage
121
- } from "./chunk-NHNXANOF.js";
124
+ } from "./chunk-TVUPVQXD.js";
122
125
  import {
123
126
  ensureLearningDir,
124
127
  getOutcomesFile
@@ -185,85 +188,6 @@ function getDefaultErrorPolicy(strategy) {
185
188
  return "reduce_denominator";
186
189
  }
187
190
 
188
- // src/cli/voter-model-overrides.ts
189
- function voterModelOverrideEnvKey(role) {
190
- return `NEXUS_VOTER_MODEL_${role.toUpperCase()}`;
191
- }
192
- function resolveVoterModelOverrides(roles, gatewayAdapters, logger12) {
193
- const overrides = /* @__PURE__ */ new Map();
194
- if (gatewayAdapters.length === 0) return overrides;
195
- const byId = /* @__PURE__ */ new Map();
196
- for (const adapter of gatewayAdapters) byId.set(adapter.modelId, adapter);
197
- for (const role of roles) {
198
- const envKey = voterModelOverrideEnvKey(role);
199
- const raw = process.env[envKey];
200
- if (raw === void 0 || raw.trim() === "") continue;
201
- const requested = raw.trim();
202
- const adapter = byId.get(requested) ?? gatewayAdapters.find((a) => a.modelId.toLowerCase() === requested.toLowerCase());
203
- if (adapter === void 0) {
204
- logger12.warn(
205
- `Voter model override ${envKey}="${requested}" is not a discovered gateway model \u2014 falling back to round-robin for role "${role}".`,
206
- { role, requested, available: [...byId.keys()] }
207
- );
208
- continue;
209
- }
210
- overrides.set(role, adapter);
211
- }
212
- if (overrides.size > 0) {
213
- logger12.info("Applied per-role voter model overrides (#4055)", {
214
- overrides: Object.fromEntries([...overrides].map(([r, a]) => [r, a.modelId]))
215
- });
216
- }
217
- return overrides;
218
- }
219
-
220
- // src/cli/voter-cli-access.ts
221
- var VOTER_ACCESS_MODE = "read-only-analysis";
222
- function clisServingVoterSeats(clis, declarationsFor = (cli) => createCliAdapter({ cli })) {
223
- const serving = [];
224
- const refused = [];
225
- for (const cli of clis) {
226
- const enforces = adapterEnforces(declarationsFor(cli), { accessMode: VOTER_ACCESS_MODE });
227
- (enforces ? serving : refused).push(cli);
228
- }
229
- return { serving, refused };
230
- }
231
-
232
- // src/cli/voter-fallback.ts
233
- function bareCliName(id) {
234
- return id.startsWith("cli-") ? id.slice("cli-".length) : id;
235
- }
236
- function classifyFallbackReason(message) {
237
- if (isDurableCapacityText(message)) return "capacity";
238
- if (isRateLimitText(message)) return "rate-limit";
239
- if (classifyExtractedError(message, "unknown").code === "NOT_AUTHENTICATED") return "auth";
240
- if (UNVERIFIABLE_STDERR_RE.test(message)) return "sandbox";
241
- if (isTimeoutText(message)) return "timeout";
242
- return "unknown";
243
- }
244
- function detectedModel(adapter) {
245
- const id = adapter.modelId;
246
- return typeof id === "string" && id !== "" && id !== UNRESOLVED_MODEL_ID ? id : void 0;
247
- }
248
- function assignedCliOf(key) {
249
- return typeof key === "string" && key !== "" ? bareCliName(key) : void 0;
250
- }
251
- function crossCliFallback(assigned, assignedKey, error) {
252
- const fromModel = detectedModel(assigned);
253
- return {
254
- fromCli: assignedCliOf(assignedKey) ?? "unknown",
255
- ...fromModel !== void 0 ? { fromModel } : {},
256
- reason: classifyFallbackReason(error)
257
- };
258
- }
259
- function inFamilyFallback(cli, fromModel) {
260
- return { fromCli: bareCliName(cli), fromModel, reason: "capacity" };
261
- }
262
- function withAssignedCli(result, assignedKey) {
263
- const assignedCli = assignedCliOf(assignedKey);
264
- return assignedCli === void 0 ? result : { ...result, assignedCli };
265
- }
266
-
267
191
  // src/cli/voter-attempt-events.ts
268
192
  import { randomUUID } from "node:crypto";
269
193
  function resolveAttemptCollector(context) {
@@ -382,6 +306,134 @@ function preserveVoterAttemptTelemetry(from, onto) {
382
306
  return initial === void 0 ? onto : withVoterAttemptTelemetry(onto, () => from.attemptTelemetry ?? initial);
383
307
  }
384
308
 
309
+ // src/cli/voter-model-overrides.ts
310
+ function voterModelOverrideEnvKey(role) {
311
+ return `NEXUS_VOTER_MODEL_${role.toUpperCase()}`;
312
+ }
313
+ function resolveVoterModelOverrides(roles, gatewayAdapters, logger12) {
314
+ const overrides = /* @__PURE__ */ new Map();
315
+ if (gatewayAdapters.length === 0) return overrides;
316
+ const byId = /* @__PURE__ */ new Map();
317
+ for (const adapter of gatewayAdapters) byId.set(adapter.modelId, adapter);
318
+ for (const role of roles) {
319
+ const envKey = voterModelOverrideEnvKey(role);
320
+ const raw = process.env[envKey];
321
+ if (raw === void 0 || raw.trim() === "") continue;
322
+ const requested = raw.trim();
323
+ const adapter = byId.get(requested) ?? gatewayAdapters.find((a) => a.modelId.toLowerCase() === requested.toLowerCase());
324
+ if (adapter === void 0) {
325
+ logger12.warn(
326
+ `Voter model override ${envKey}="${requested}" is not a discovered gateway model \u2014 falling back to round-robin for role "${role}".`,
327
+ { role, requested, available: [...byId.keys()] }
328
+ );
329
+ continue;
330
+ }
331
+ overrides.set(role, adapter);
332
+ }
333
+ if (overrides.size > 0) {
334
+ logger12.info("Applied per-role voter model overrides (#4055)", {
335
+ overrides: Object.fromEntries([...overrides].map(([r, a]) => [r, a.modelId]))
336
+ });
337
+ }
338
+ return overrides;
339
+ }
340
+ function ignoredRolePinReason(requested, options) {
341
+ const gateway = options.gatewayAdapters ?? [];
342
+ if (gateway.length === 0) {
343
+ return hasGatewaySlotCatalog() ? "gateway model dealing is inactive for this panel" : "no gateway active";
344
+ }
345
+ if (options.adapter !== void 0) return "an explicit adapter overrides gateway dealing";
346
+ if (options.roleAdapters !== void 0) return "the roster was assigned before this call";
347
+ if (gateway.length === 1) return "single-model gateway: role pins have no effect";
348
+ if (!gateway.some((a) => a.modelId.toLowerCase() === requested.toLowerCase())) {
349
+ return "not in the gateway catalog; the seat was dealt instead";
350
+ }
351
+ return void 0;
352
+ }
353
+ function ignoredCustomPin(gateway) {
354
+ const requested = process.env["NEXUS_CUSTOM_MODEL"]?.trim();
355
+ if (requested === void 0 || requested === "") return void 0;
356
+ if (gateway.length > 0) {
357
+ if (gateway.some((a) => a.modelId === requested)) return void 0;
358
+ } else {
359
+ const resolved = resolveGatewayDefault();
360
+ if (resolved.kind === "inactive" || resolved.kind === "resolved" && resolved.via === "override") {
361
+ return void 0;
362
+ }
363
+ }
364
+ return `NEXUS_CUSTOM_MODEL="${requested}" ignored: not in the gateway catalog`;
365
+ }
366
+ function captureModelPinWarnings(options) {
367
+ const ignored = /* @__PURE__ */ new Map();
368
+ const custom = ignoredCustomPin(options.gatewayAdapters ?? []);
369
+ for (const role of options.roles) {
370
+ const key = voterModelOverrideEnvKey(role);
371
+ const requested = process.env[key]?.trim();
372
+ let roleWarning;
373
+ if (requested !== void 0 && requested !== "") {
374
+ const reason = ignoredRolePinReason(requested, options);
375
+ if (reason !== void 0) roleWarning = `${key}="${requested}" ignored: ${reason}`;
376
+ }
377
+ const warning = [roleWarning, custom].filter((w) => w !== void 0).join("; ");
378
+ if (warning !== "") ignored.set(role, warning);
379
+ }
380
+ return (vote) => {
381
+ const warning = ignored.get(vote.role);
382
+ if (warning === void 0) return vote;
383
+ return preserveVoterAttemptTelemetry(vote, {
384
+ ...vote,
385
+ modelPinWarning: `${warning}; role "${vote.role}" assigned model "${vote.pinnedModel ?? "unresolved"}".`
386
+ });
387
+ };
388
+ }
389
+
390
+ // src/cli/voter-cli-access.ts
391
+ var VOTER_ACCESS_MODE = "read-only-analysis";
392
+ function clisServingVoterSeats(clis, declarationsFor = (cli) => createCliAdapter({ cli })) {
393
+ const serving = [];
394
+ const refused = [];
395
+ for (const cli of clis) {
396
+ const enforces = adapterEnforces(declarationsFor(cli), { accessMode: VOTER_ACCESS_MODE });
397
+ (enforces ? serving : refused).push(cli);
398
+ }
399
+ return { serving, refused };
400
+ }
401
+
402
+ // src/cli/voter-fallback.ts
403
+ function bareCliName(id) {
404
+ return id.startsWith("cli-") ? id.slice("cli-".length) : id;
405
+ }
406
+ function classifyFallbackReason(message) {
407
+ if (isDurableCapacityText(message)) return "capacity";
408
+ if (isRateLimitText(message)) return "rate-limit";
409
+ if (classifyExtractedError(message, "unknown").code === "NOT_AUTHENTICATED") return "auth";
410
+ if (UNVERIFIABLE_STDERR_RE.test(message)) return "sandbox";
411
+ if (isTimeoutText(message)) return "timeout";
412
+ return "unknown";
413
+ }
414
+ function detectedModel(adapter) {
415
+ const id = adapter.modelId;
416
+ return typeof id === "string" && id !== "" && id !== UNRESOLVED_MODEL_ID ? id : void 0;
417
+ }
418
+ function assignedCliOf(key) {
419
+ return typeof key === "string" && key !== "" ? bareCliName(key) : void 0;
420
+ }
421
+ function crossCliFallback(assigned, assignedKey, error) {
422
+ const fromModel = detectedModel(assigned);
423
+ return {
424
+ fromCli: assignedCliOf(assignedKey) ?? "unknown",
425
+ ...fromModel !== void 0 ? { fromModel } : {},
426
+ reason: classifyFallbackReason(error)
427
+ };
428
+ }
429
+ function inFamilyFallback(cli, fromModel) {
430
+ return { fromCli: bareCliName(cli), fromModel, reason: "capacity" };
431
+ }
432
+ function withAssignedCli(result, assignedKey) {
433
+ const assignedCli = assignedCliOf(assignedKey);
434
+ return assignedCli === void 0 ? result : { ...result, assignedCli };
435
+ }
436
+
385
437
  // src/cli/voter-cancel.ts
386
438
  var SEAT_CANCELLED_MESSAGE = "cancelled while this voter was in flight";
387
439
  function isCancelled(signal) {
@@ -2305,6 +2357,7 @@ async function collectRealVotes(options) {
2305
2357
  if ("simulated" in adapterResult)
2306
2358
  return createSimulatedVotes(roles, proposal, "No adapter available");
2307
2359
  const roleAdapters = await assignPanelSeats(adapterResult.adapter, options, logger12);
2360
+ const discloseModelPins = captureModelPinWarnings(options);
2308
2361
  warnIfCodexConcurrencyExceeded(roleAdapters, logger12);
2309
2362
  const workspace = resolvePanelWorkspace(options.workspace);
2310
2363
  const { nonRetryableRoles, onError } = createVoterRetryState();
@@ -2335,7 +2388,7 @@ async function collectRealVotes(options) {
2335
2388
  options.erroredRoleBackoffMs ?? DEFAULT_ERRORED_ROLE_BACKOFF_MS
2336
2389
  );
2337
2390
  reportVoteIndependence(results, logger12);
2338
- return results;
2391
+ return results.map(discloseModelPins);
2339
2392
  }
2340
2393
 
2341
2394
  // src/cli/vote-artifact.ts
@@ -5948,6 +6001,15 @@ function panelDiversityOf(votes) {
5948
6001
  fallbacks: seatFallbacks(votes).length
5949
6002
  };
5950
6003
  }
6004
+ function assignedPanelDiversityOf(votes) {
6005
+ const models = votes.map((v) => v.pinnedModel).filter((m) => m !== void 0 && m !== "" && m !== UNRESOLVED_MODEL_ID);
6006
+ if (models.length === 0) return {};
6007
+ const families = models.map(vendorFamilyOf).filter((family) => family !== "unknown");
6008
+ return {
6009
+ assignedDistinctModels: countDistinctModels(models),
6010
+ assignedDistinctFamilies: new Set(families).size
6011
+ };
6012
+ }
5951
6013
  var MIN_PANEL_FOR_DIVERSITY_WARNING = 3;
5952
6014
  function singleModelPanelWarning(votes) {
5953
6015
  if (votes.length < MIN_PANEL_FOR_DIVERSITY_WARNING) return void 0;
@@ -5970,6 +6032,21 @@ function singleFamilyPanelWarning(votes) {
5970
6032
  if (distinctFamilies !== 1 || unclassifiedSeats > 0 || distinctModels < 2) return void 0;
5971
6033
  return `All ${String(answered.length)} answering seats ran ${vendorFamilyOf(model)} models (${String(distinctModels)} distinct); independence is weaker than assigned.`;
5972
6034
  }
6035
+ function assignedFallbackFamily(v, fallback) {
6036
+ const model = resolvedModel({ ...v, model: fallback.fromModel ?? v.pinnedModel });
6037
+ return vendorFamilyOf(model ?? CLI_TO_MODELSDEV_VENDOR[fallback.fromCli] ?? "");
6038
+ }
6039
+ function crossFamilyFallbackWarning(votes) {
6040
+ const changes = [];
6041
+ for (const v of answeringSeats(votes)) {
6042
+ if (v.fallback === void 0) continue;
6043
+ const assigned = assignedFallbackFamily(v, v.fallback);
6044
+ const served = vendorFamilyOf(resolvedModel(v) ?? "");
6045
+ if (assigned === "unknown" || served === "unknown" || assigned === served) continue;
6046
+ changes.push(`${v.role}: assigned ${assigned}, served ${served}`);
6047
+ }
6048
+ return changes.length === 0 ? void 0 : `Cross-family fallback: ${changes.join("; ")}.`;
6049
+ }
5973
6050
 
5974
6051
  // src/mcp/tools/consensus-vote-option-detection.ts
5975
6052
  var UNDECLARED_OPTION_PATTERNS = Object.freeze([
@@ -6170,7 +6247,8 @@ function toAgentVoteSummary(result) {
6170
6247
  // #6246: and for what a recovered seat was retried from.
6171
6248
  ...result.retriedFrom !== void 0 ? { retriedFrom: result.retriedFrom } : {},
6172
6249
  // #6606: the per-seat model was only in `costSummary.perVoter`.
6173
- ...modelUsedOf(result)
6250
+ ...modelUsedOf(result),
6251
+ ...assignedModelOf(result)
6174
6252
  };
6175
6253
  }
6176
6254
  var MODEL_USED_MAX_CHARS = 100;
@@ -6181,6 +6259,13 @@ function modelUsedOf(result) {
6181
6259
  modelUsed: model.length <= MODEL_USED_MAX_CHARS ? model : `${model.slice(0, MODEL_USED_MAX_CHARS - 1)}\u2026`
6182
6260
  };
6183
6261
  }
6262
+ function assignedModelOf(result) {
6263
+ const model = result.pinnedModel;
6264
+ if (model === void 0 || model === "" || model === UNRESOLVED_MODEL_ID) return {};
6265
+ return {
6266
+ assignedModel: model.length <= MODEL_USED_MAX_CHARS ? model : `${model.slice(0, MODEL_USED_MAX_CHARS - 1)}\u2026`
6267
+ };
6268
+ }
6184
6269
  function panelDegradationWarning(errorCount, total) {
6185
6270
  if (errorCount <= 0 || errorCount >= total) return void 0;
6186
6271
  return `Panel degraded: ${String(errorCount)} of ${String(total)} voters errored; decision rests on ${String(total - errorCount)} voter(s).`;
@@ -6189,9 +6274,11 @@ function appendPanelWarning(response, text) {
6189
6274
  if (text === void 0) return;
6190
6275
  response.panelWarning = response.panelWarning === void 0 ? text : `${response.panelWarning} ${text}`;
6191
6276
  }
6192
- function unverifiableSeatsWarning(unverifiableCount, total) {
6277
+ function unverifiableSeatsWarning(unverifiableCount, total, artifactPath) {
6193
6278
  if (unverifiableCount <= 0) return void 0;
6194
- return `${String(unverifiableCount)} of ${String(total)} seat(s) could not read the artifact and are recorded as unverifiable (counted as abstain in voteCounts; any decision they returned was discarded).`;
6279
+ const warning = `${String(unverifiableCount)} of ${String(total)} seat(s) could not read the artifact and are recorded as unverifiable (counted as abstain in voteCounts; any decision they returned was discarded).`;
6280
+ if (artifactPath !== void 0) return warning;
6281
+ return `${warning} No artifactPath was supplied: voters only see the proposal text; pass artifactPath (or inline the artifact) so they can inspect it.`;
6195
6282
  }
6196
6283
  var degradedPanelCount = 0;
6197
6284
  function applyAbsoluteQuorumTelemetry(response, input, decision, degradeReason) {
@@ -6246,6 +6333,7 @@ function buildResponse(input, result, costSummary, voteRecord) {
6246
6333
  ...disclosedWorkspace(result),
6247
6334
  // #6115: always present — a panel nobody answered is explicit zeros.
6248
6335
  panelDiversity: panelDiversityOf(result.votes),
6336
+ ...assignedPanelDiversityOf(result.votes),
6249
6337
  // #3991: surface the authentic-vote-record persistence outcome so a skipped
6250
6338
  // or failed persist is visible to the MCP caller (was WARN-only).
6251
6339
  voteRecordPersisted: voteRecord?.persisted ?? false
@@ -6284,12 +6372,18 @@ function applyOptionalResponseFields(response, input, result, errorCount, costSu
6284
6372
  if (panelWarning !== void 0) {
6285
6373
  response.panelWarning = panelWarning;
6286
6374
  }
6375
+ for (const vote of result.votes) appendPanelWarning(response, vote.modelPinWarning);
6287
6376
  appendPanelWarning(
6288
6377
  response,
6289
- unverifiableSeatsWarning(response.voteCounts.unverifiable, result.votes.length)
6378
+ unverifiableSeatsWarning(
6379
+ response.voteCounts.unverifiable,
6380
+ result.votes.length,
6381
+ input.artifactPath
6382
+ )
6290
6383
  );
6291
6384
  appendPanelWarning(response, singleModelPanelWarning(result.votes));
6292
6385
  appendPanelWarning(response, singleFamilyPanelWarning(result.votes));
6386
+ appendPanelWarning(response, crossFamilyFallbackWarning(result.votes));
6293
6387
  const engaged = result.votes.length - errorCount;
6294
6388
  const undeclared = checkUndeclaredOptions(
6295
6389
  input.proposal,
@@ -6400,7 +6494,7 @@ function logPartialProposal(bounded, log) {
6400
6494
  }
6401
6495
  async function runContrarianCheck(proposal, options, log, opts) {
6402
6496
  try {
6403
- const { executeExpert } = await import("./expert-bridge-JEZYYPHE.js");
6497
+ const { executeExpert } = await import("./expert-bridge-S4LEWNOQ.js");
6404
6498
  const bounded = boundArtifactForReview(proposal, CONTRARIAN_PROPOSAL_BUDGET, "proposal");
6405
6499
  logPartialProposal(bounded, log);
6406
6500
  const result = await executeExpert(
@@ -9344,6 +9438,7 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
9344
9438
  reason: z15.enum(["rate-limit", "capacity", "auth", "timeout", "sandbox", "unknown"])
9345
9439
  }).optional(),
9346
9440
  modelUsed: z15.string().max(100).optional(),
9441
+ assignedModel: z15.string().max(100).optional(),
9347
9442
  rejectionCategories: z15.array(
9348
9443
  z15.enum([
9349
9444
  "YAGNI",
@@ -9412,6 +9507,10 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
9412
9507
  unresolvedSeats: z15.number().int().nonnegative().optional(),
9413
9508
  fallbacks: z15.number().int().nonnegative()
9414
9509
  }).optional(),
9510
+ // Assigned roster includes errored and abstaining seats. Absent when no
9511
+ // assignment resolved, including a zero-seat roster.
9512
+ assignedDistinctModels: z15.number().int().nonnegative().optional(),
9513
+ assignedDistinctFamilies: z15.number().int().nonnegative().optional(),
9415
9514
  // #3855: per-decision cost rollup. Same omission as panelWarning (#4032) — it
9416
9515
  // is present on the response whenever cost recording succeeds (common in `api`
9417
9516
  // billing mode). Shared schema lives with the type (single source of truth).
@@ -9434,7 +9533,7 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
9434
9533
  }).optional()
9435
9534
  };
9436
9535
  var CONSENSUS_VOTE_TOOL_SCHEMA = ConsensusVoteInputSchema.shape;
9437
- var CONSENSUS_VOTE_DESCRIPTION = "Execute multi-model consensus voting on a proposal. Uses 7 roles by default (architect, security, devex, ai_ml, pm, catfish, scope_steward) or 3 with quickMode (architect, security, scope_steward), voting with configurable strategies. higher_order does NOT decide the verdict by correlation-aware aggregation (#4701): approve/reject is a simple tally of the panel, so correlated voters each carry full independent weight. The Bayesian correlation analysis is computed and feeds contrarian escalation only. Choose it for the escalation behaviour, not for a weighted verdict. Supports async dispatch (dispatch: 'async') \u2014 returns a jobId to poll via get_job_result. Pass ratifies=<subject> to bind an authority-ladder ratification vote into its authentic record, and ratifiesPr={pr, headSha} to bind a governor-path PR ratification to the head the panel saw (#5130); the result carries voteRecordId for the caller-commits append. If your proposal asks voters to choose among named alternatives, you MUST pass them in `options` (#4472) \u2014 the threshold is then measured over WHICH option won, and the record carries the per-option tally plus selection coverage. WITHOUT `options` the tally is approve/reject/abstain only, so every voter who engages returns `approve` and a 6-1 split on which option persists as 7-0, 100% (#4452).";
9536
+ var CONSENSUS_VOTE_DESCRIPTION = "Execute multi-model consensus voting on a proposal. Uses 7 roles by default (architect, security, devex, ai_ml, pm, catfish, scope_steward) or 3 with quickMode (architect, security, scope_steward), voting with configurable strategies. higher_order does NOT decide the verdict by correlation-aware aggregation (#4701): approve/reject is a simple tally of the panel, so correlated voters each carry full independent weight. The Bayesian correlation analysis is computed and feeds contrarian escalation only. Choose it for the escalation behaviour, not for a weighted verdict. Supports async dispatch (dispatch: 'async') \u2014 returns a jobId to poll via get_job_result. Pass ratifies=<subject> to bind an authority-ladder ratification vote into its authentic record, and ratifiesPr={pr, headSha} to bind a governor-path PR ratification to the head the panel saw (#5130); the result carries voteRecordId for the caller-commits append. If your proposal asks voters to choose among named alternatives, you MUST pass them in `options` (#4472) \u2014 the threshold is then measured over WHICH option won, and the record carries the per-option tally plus selection coverage. WITHOUT `options` the tally is approve/reject/abstain only, so every voter who engages returns `approve` and a 6-1 split on which option persists as 7-0, 100% (#4452). The response separates responding panelDiversity from optional assignedDistinctModels and assignedDistinctFamilies, and votes[].assignedModel shows each resolved assignment, including errored or abstaining seats. Assignment counts are omitted when unmeasured. panelWarning names ignored model pins and includes an artifactPath hint when unverifiable seats had no supplied artifact.";
9438
9537
  function registerConsensusVoteTool(server, deps) {
9439
9538
  const logger12 = deps.logger ?? createLogger({ tool: "consensus_vote" });
9440
9539
  const notifier = deps.notifier ?? createMcpNotifier(server);
@@ -9577,4 +9676,4 @@ export {
9577
9676
  CONSENSUS_VOTE_TOOL_SCHEMA,
9578
9677
  registerConsensusVoteTool
9579
9678
  };
9580
- //# sourceMappingURL=chunk-GZHDEMLN.js.map
9679
+ //# sourceMappingURL=chunk-JU4YPMVT.js.map