nexus-agents 2.151.1 → 2.152.0

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.
@@ -8,7 +8,7 @@ import {
8
8
  checkSqlite,
9
9
  defaultConfig,
10
10
  initDataDirectories
11
- } from "./chunk-SJFARLAQ.js";
11
+ } from "./chunk-GKZ3GPB3.js";
12
12
  import {
13
13
  BUILT_IN_EXPERTS
14
14
  } from "./chunk-ZM4O442V.js";
@@ -2000,4 +2000,4 @@ export {
2000
2000
  setupCommand,
2001
2001
  setupCommandAsync
2002
2002
  };
2003
- //# sourceMappingURL=chunk-QL4Q3HUO.js.map
2003
+ //# sourceMappingURL=chunk-FOC2KDKV.js.map
@@ -42,7 +42,7 @@ import {
42
42
  } from "./chunk-DHVMSIT5.js";
43
43
 
44
44
  // src/version.ts
45
- var VERSION = true ? "2.151.1" : "dev";
45
+ var VERSION = true ? "2.152.0" : "dev";
46
46
 
47
47
  // src/config/schemas-core.ts
48
48
  import { z } from "zod";
@@ -2132,7 +2132,7 @@ async function runDoctorFix(result) {
2132
2132
  writeLine2("\u2500".repeat(40));
2133
2133
  let fixCount = 0;
2134
2134
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
2135
- const { runSetup } = await import("./setup-command-IQ7WFZIM.js");
2135
+ const { runSetup } = await import("./setup-command-EQ6XG2QV.js");
2136
2136
  const setupResult = runSetup({
2137
2137
  skipMcp: true,
2138
2138
  skipRules: true,
@@ -2245,4 +2245,4 @@ export {
2245
2245
  startStdioServer,
2246
2246
  closeServer
2247
2247
  };
2248
- //# sourceMappingURL=chunk-SJFARLAQ.js.map
2248
+ //# sourceMappingURL=chunk-GKZ3GPB3.js.map
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { C as CliNameLiteral, e as VoteThreshold, E as ErrorPolicy } from './consensus-vote-types-DOCnPzfx.js';
2
+ import { C as CliNameLiteral, J as VoteThreshold, K as ErrorPolicy, N as NoQuorumPolicy } from './consensus-vote-types-B06ynHGk.js';
3
3
  import 'zod';
4
4
 
5
5
  /**
@@ -79,6 +79,8 @@ interface ParsedCliArgs {
79
79
  timeoutMs?: number;
80
80
  /** #2630 — see `applyErrorPolicy`. */
81
81
  errorPolicy?: ErrorPolicy;
82
+ /** #4135 — how the vote command maps a `no_quorum` decision. Default `fail`. */
83
+ onNoQuorum?: NoQuorumPolicy;
82
84
  variant?: 'lite' | 'verified' | 'full';
83
85
  limit?: number;
84
86
  instance?: string[];
package/dist/cli.js CHANGED
@@ -22,7 +22,7 @@ import "./chunk-M4YN3U3P.js";
22
22
  import {
23
23
  setupCommandAsync,
24
24
  verifyCommand
25
- } from "./chunk-QL4Q3HUO.js";
25
+ } from "./chunk-FOC2KDKV.js";
26
26
  import "./chunk-CD7FU55Z.js";
27
27
  import {
28
28
  AuthHandler,
@@ -142,7 +142,7 @@ import {
142
142
  validateCommand,
143
143
  validateWorkflow,
144
144
  wrapInMarkdownFence
145
- } from "./chunk-IR7FP4SS.js";
145
+ } from "./chunk-4RJB246Z.js";
146
146
  import "./chunk-CMAQI2SJ.js";
147
147
  import "./chunk-T2SGTVB4.js";
148
148
  import "./chunk-HFOQKCD2.js";
@@ -170,7 +170,7 @@ import {
170
170
  loadConfig,
171
171
  runDoctor,
172
172
  validateNexusEnv
173
- } from "./chunk-SJFARLAQ.js";
173
+ } from "./chunk-GKZ3GPB3.js";
174
174
  import "./chunk-GMQH2I4P.js";
175
175
  import {
176
176
  shutdownExpertBridge
@@ -182,8 +182,9 @@ import {
182
182
  VOTER_ROLES,
183
183
  VoteThresholdSchema,
184
184
  executeVoting,
185
+ mapOutcomeToDecision,
185
186
  registerConsensusVoteTool
186
- } from "./chunk-UIL37D2V.js";
187
+ } from "./chunk-447YUGJD.js";
187
188
  import {
188
189
  loadUsageEvents,
189
190
  rollupByModel
@@ -3469,6 +3470,10 @@ var PARSE_ARGS_CONFIG = {
3469
3470
  "error-policy": {
3470
3471
  type: "string"
3471
3472
  },
3473
+ // #4135 — how the vote command maps a no_quorum decision (fail|exit2|retry).
3474
+ "on-no-quorum": {
3475
+ type: "string"
3476
+ },
3472
3477
  // SWE-bench command options
3473
3478
  variant: {
3474
3479
  type: "string",
@@ -6915,20 +6920,30 @@ function validateGitHubIssue(issueNumber) {
6915
6920
  });
6916
6921
  return output2 !== null;
6917
6922
  }
6918
- function formatVoteComment(result) {
6923
+ function decisionResultLabel(decision) {
6924
+ switch (decision) {
6925
+ case "approved":
6926
+ return { emoji: "\u2705", text: "APPROVED" };
6927
+ case "no_quorum":
6928
+ return { emoji: "\u26A0\uFE0F", text: "NO QUORUM" };
6929
+ default:
6930
+ return { emoji: "\u274C", text: decision.toUpperCase() };
6931
+ }
6932
+ }
6933
+ function formatVoteComment(result, decision) {
6919
6934
  const now = new Date(getTimeProvider().now()).toLocaleDateString("en-US", {
6920
6935
  timeZone: "America/New_York",
6921
6936
  year: "numeric",
6922
6937
  month: "2-digit",
6923
6938
  day: "2-digit"
6924
6939
  });
6925
- const outcomeEmoji = result.result.outcome === "approved" ? "\u2705" : "\u274C";
6926
- const outcomeText = result.result.outcome.toUpperCase();
6940
+ const effectiveDecision = decision ?? mapOutcomeToDecision(result.result.outcome);
6941
+ const { emoji: outcomeEmoji, text: outcomeText } = decisionResultLabel(effectiveDecision);
6927
6942
  const voteRows = result.votes.map(({ role, vote }) => {
6928
6943
  const roleLabel = VOTER_ROLES[role].split(" - ")[0] ?? role;
6929
- const decision = vote.decision.toUpperCase();
6944
+ const decision2 = vote.decision.toUpperCase();
6930
6945
  const confidence = formatPercentage(vote.confidence);
6931
- return `| ${roleLabel} | ${decision} | ${confidence} |`;
6946
+ return `| ${roleLabel} | ${decision2} | ${confidence} |`;
6932
6947
  }).join("\n");
6933
6948
  const { voteCounts, approvalPercentage } = result.result;
6934
6949
  const summary = `Approve: ${String(voteCounts.approve)}, Reject: ${String(voteCounts.reject)}, Abstain: ${String(voteCounts.abstain)} (${approvalPercentage.toFixed(1)}% approval)`;
@@ -6949,8 +6964,8 @@ ${voteRows}
6949
6964
  ---
6950
6965
  *Vote conducted per CLAUDE.md Consensus Voting Protocol*`;
6951
6966
  }
6952
- function recordVoteToGitHub(issueNumber, result) {
6953
- const comment = formatVoteComment(result);
6967
+ function recordVoteToGitHub(issueNumber, result, decision) {
6968
+ const comment = formatVoteComment(result, decision);
6954
6969
  const output2 = safeExecSandboxed(`gh issue comment ${String(issueNumber)} --body-file -`, {
6955
6970
  context: "gh",
6956
6971
  stdin: comment
@@ -6996,7 +7011,8 @@ async function runVote(options) {
6996
7011
  result: result.result,
6997
7012
  votes: result.votes,
6998
7013
  totalTimeMs: result.totalTimeMs,
6999
- simulateVotes: result.simulateVotes
7014
+ simulateVotes: result.simulateVotes,
7015
+ decision: result.decision ?? mapOutcomeToDecision(result.result.outcome)
7000
7016
  };
7001
7017
  }
7002
7018
  function printDryRunBanner() {
@@ -7023,7 +7039,7 @@ function validateIssueIfNeeded(issueNumber) {
7023
7039
  `);
7024
7040
  return true;
7025
7041
  }
7026
- function handleRecording(options, result) {
7042
+ function handleRecording(options, result, decision) {
7027
7043
  if (options.issueNumber === void 0) return;
7028
7044
  if (options.dryRun === true) {
7029
7045
  writeLine(
@@ -7031,9 +7047,14 @@ function handleRecording(options, result) {
7031
7047
  `
7032
7048
  );
7033
7049
  } else {
7034
- recordVoteToGitHub(options.issueNumber, result);
7050
+ recordVoteToGitHub(options.issueNumber, result, decision);
7035
7051
  }
7036
7052
  }
7053
+ function exitCodeForDecision(decision, policy) {
7054
+ if (decision === "approved") return 0;
7055
+ if (decision === "no_quorum") return policy === "exit2" ? 2 : 1;
7056
+ return 1;
7057
+ }
7037
7058
  async function voteCommand(options) {
7038
7059
  writeLine(`
7039
7060
  ${colors.bold}Nexus Agents Consensus Vote${colors.reset}`);
@@ -7044,15 +7065,23 @@ ${colors.bold}Nexus Agents Consensus Vote${colors.reset}`);
7044
7065
  `${colors.dim}Proposal: ${options.proposal.slice(0, 100)}${options.proposal.length > 100 ? "..." : ""}${colors.reset}
7045
7066
  `
7046
7067
  );
7068
+ const onNoQuorum = options.onNoQuorum ?? "fail";
7047
7069
  try {
7048
- const result = await runVote(options);
7070
+ let result = await runVote(options);
7071
+ if (result.decision === "no_quorum" && onNoQuorum === "retry") {
7072
+ writeLine(
7073
+ `${colors.yellow}No quorum \u2014 re-running the vote once (--on-no-quorum=retry)...${colors.reset}
7074
+ `
7075
+ );
7076
+ result = await runVote(options);
7077
+ }
7049
7078
  printVoteDetails(result.votes);
7050
7079
  printSummary2({ result: result.result, votes: result.votes, threshold: result.threshold });
7051
7080
  if (options.verbose === true) printHashes(result.votes);
7052
7081
  writeLine(`${colors.dim}Completed in ${String(result.totalTimeMs)}ms${colors.reset}
7053
7082
  `);
7054
- handleRecording(options, result);
7055
- return result.result.outcome === "approved" ? 0 : 1;
7083
+ handleRecording(options, result, result.decision);
7084
+ return exitCodeForDecision(result.decision, onNoQuorum);
7056
7085
  } catch (error) {
7057
7086
  writeLine(`${colors.red}Error: ${getErrorMessage(error)}${colors.reset}`);
7058
7087
  return 1;
@@ -20452,6 +20481,10 @@ var VOTE_HELP = {
20452
20481
  flag: "--error-policy <p>",
20453
20482
  description: "How to count errored/timed-out voters: reduce_denominator | count_as_abstain | fail_closed | absolute_quorum (#4132 \u2014 an errored voter degrades the verdict to no_quorum) (default: fail_closed for unanimous, reduce_denominator otherwise)"
20454
20483
  },
20484
+ {
20485
+ flag: "--on-no-quorum <p>",
20486
+ description: "How to map a no_quorum decision (#4135): fail (exit 1, default) | exit2 (distinct exit 2) | retry (re-run once, then fail)"
20487
+ },
20455
20488
  { flag: "--verbose", description: "Show vote verification hashes" }
20456
20489
  ],
20457
20490
  requiresApiKey: ["ANTHROPIC_API_KEY", "OPENAI_API_KEY", "GOOGLE_AI_API_KEY"]
@@ -20927,11 +20960,12 @@ async function handleVoteCommand(args) {
20927
20960
  proposal,
20928
20961
  ...validThreshold !== void 0 && { threshold: validThreshold },
20929
20962
  ...validErrorPolicy !== void 0 && { errorPolicy: validErrorPolicy },
20963
+ ...args.options.onNoQuorum !== void 0 && { onNoQuorum: args.options.onNoQuorum },
20930
20964
  dryRun: args.options.dryRun,
20931
20965
  quick: args.options.quick,
20932
20966
  verbose: args.options.verbose
20933
20967
  });
20934
- return cliExitFromStatus(exitCode);
20968
+ return cliExit(exitCode);
20935
20969
  }
20936
20970
  async function handleIndexCommand2(args) {
20937
20971
  const subcommand = args.subcommand;
@@ -25673,16 +25707,22 @@ function parseErrorPolicy(value) {
25673
25707
  const parsed = ErrorPolicySchema.safeParse(value);
25674
25708
  return parsed.success ? parsed.data : void 0;
25675
25709
  }
25710
+ function parseNoQuorumPolicy(value) {
25711
+ if (value === "fail" || value === "exit2" || value === "retry") return value;
25712
+ return void 0;
25713
+ }
25676
25714
  function buildVoteOptions(values) {
25677
25715
  const threshold = parseThreshold(values.threshold);
25678
25716
  const timeoutSec = parseNumericOption(values.timeout);
25679
25717
  const timeoutMs = timeoutSec !== void 0 ? timeoutSec * 1e3 : void 0;
25680
25718
  const errorPolicy = parseErrorPolicy(values["error-policy"]);
25719
+ const onNoQuorum = parseNoQuorumPolicy(values["on-no-quorum"]);
25681
25720
  return {
25682
25721
  ...values.proposal !== void 0 && { proposal: values.proposal },
25683
25722
  ...threshold !== void 0 && { threshold },
25684
25723
  ...timeoutMs !== void 0 && { timeoutMs },
25685
- ...errorPolicy !== void 0 && { errorPolicy }
25724
+ ...errorPolicy !== void 0 && { errorPolicy },
25725
+ ...onNoQuorum !== void 0 && { onNoQuorum }
25686
25726
  };
25687
25727
  }
25688
25728
  function parseSweBenchVariant(value) {