nexus-agents 8.56.0 → 8.57.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.
@@ -7,7 +7,7 @@ import {
7
7
  toolStructuredError,
8
8
  toolSuccessStructured,
9
9
  wrapToolWithTimeout
10
- } from "./chunk-BWP3RTR2.js";
10
+ } from "./chunk-VCLNGU3S.js";
11
11
  import {
12
12
  JsonlStore,
13
13
  SECURITY_KEYWORDS,
@@ -2278,4 +2278,4 @@ export {
2278
2278
  runImprovementReview,
2279
2279
  registerImprovementReviewTool
2280
2280
  };
2281
- //# sourceMappingURL=chunk-5W55WXLY.js.map
2281
+ //# sourceMappingURL=chunk-3KOCMFOK.js.map
@@ -1,6 +1,6 @@
1
1
  // src/version.ts
2
2
  import semver from "semver";
3
- var VERSION = true ? "8.56.0" : "dev";
3
+ var VERSION = true ? "8.57.0" : "dev";
4
4
  var NODE_ENGINE_RANGE = ">=22.5.0";
5
5
  function isNodeVersionSupported(version) {
6
6
  return semver.satisfies(version, NODE_ENGINE_RANGE);
@@ -11,4 +11,4 @@ export {
11
11
  NODE_ENGINE_RANGE,
12
12
  isNodeVersionSupported
13
13
  };
14
- //# sourceMappingURL=chunk-UURJGJTW.js.map
14
+ //# sourceMappingURL=chunk-H3PRTTXF.js.map
@@ -11,7 +11,7 @@ import {
11
11
  NODE_ENGINE_RANGE,
12
12
  VERSION,
13
13
  isNodeVersionSupported
14
- } from "./chunk-UURJGJTW.js";
14
+ } from "./chunk-H3PRTTXF.js";
15
15
  import {
16
16
  claimGlobalRegistry
17
17
  } from "./chunk-BXP5K5TU.js";
@@ -1314,7 +1314,7 @@ async function runDoctorFix(result) {
1314
1314
  writeLine2("\u2500".repeat(40));
1315
1315
  let fixCount = 0;
1316
1316
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
1317
- const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-RXY2PWDX.js");
1317
+ const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-3JC2SSZ4.js");
1318
1318
  const outcome = describeDataDirFix2(initDataDirectories2());
1319
1319
  writeLine2(outcome.line);
1320
1320
  if (outcome.counted) fixCount++;
@@ -1416,4 +1416,4 @@ export {
1416
1416
  startStdioServer,
1417
1417
  closeServer
1418
1418
  };
1419
- //# sourceMappingURL=chunk-M2ZQXDSO.js.map
1419
+ //# sourceMappingURL=chunk-IJMAA7MV.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-UURJGJTW.js";
3
+ } from "./chunk-H3PRTTXF.js";
4
4
  import {
5
5
  emitClawGuardViolation
6
6
  } from "./chunk-VZSMNIRN.js";
@@ -2378,4 +2378,4 @@ export {
2378
2378
  DEFAULT_CONSENSUS_CONFIG,
2379
2379
  ConsensusMetricsSchema
2380
2380
  };
2381
- //# sourceMappingURL=chunk-BWP3RTR2.js.map
2381
+ //# sourceMappingURL=chunk-VCLNGU3S.js.map
@@ -21,7 +21,7 @@ import {
21
21
  import {
22
22
  DEFAULT_TASK_TTL_MS,
23
23
  clampTaskTtl
24
- } from "./chunk-M2ZQXDSO.js";
24
+ } from "./chunk-IJMAA7MV.js";
25
25
  import {
26
26
  executeExpert
27
27
  } from "./chunk-QMGMD6JB.js";
@@ -62,7 +62,7 @@ import {
62
62
  toJobSummary,
63
63
  updateStage,
64
64
  writeJobCancelled
65
- } from "./chunk-MO6FSEFJ.js";
65
+ } from "./chunk-XU72ZQ5Z.js";
66
66
  import {
67
67
  allOf,
68
68
  anyOf
@@ -82,7 +82,7 @@ import {
82
82
  } from "./chunk-RNWUIQTZ.js";
83
83
  import {
84
84
  withPrerequisite
85
- } from "./chunk-5W55WXLY.js";
85
+ } from "./chunk-3KOCMFOK.js";
86
86
  import {
87
87
  NOOP_NOTIFIER,
88
88
  RateLimiter,
@@ -107,7 +107,7 @@ import {
107
107
  withAuditTrail,
108
108
  withProgressHeartbeat,
109
109
  wrapToolWithTimeout
110
- } from "./chunk-BWP3RTR2.js";
110
+ } from "./chunk-VCLNGU3S.js";
111
111
  import {
112
112
  createAuditTrail,
113
113
  createGraphAuditBridge,
@@ -46182,7 +46182,7 @@ function buildVotingInput(plan, config) {
46182
46182
  }
46183
46183
  async function executeSingleVote(plan, config, log) {
46184
46184
  try {
46185
- const { executeVoting } = await import("./consensus-vote-JHCRRDH5.js");
46185
+ const { executeVoting } = await import("./consensus-vote-ITVEKN2M.js");
46186
46186
  const input = buildVotingInput(plan, config);
46187
46187
  const result = await executeVoting(input, log);
46188
46188
  return parseVotingResult(result);
@@ -47980,7 +47980,7 @@ ${contextBlock}`;
47980
47980
  const strategy = config.votingStrategy ?? "higher_order";
47981
47981
  await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
47982
47982
  try {
47983
- const { executeVoting } = await import("./consensus-vote-JHCRRDH5.js");
47983
+ const { executeVoting } = await import("./consensus-vote-ITVEKN2M.js");
47984
47984
  const votingResult = await executeVoting(
47985
47985
  {
47986
47986
  proposal: buildVoteProposal(plan, research),
@@ -57179,4 +57179,4 @@ export {
57179
57179
  startPipelineEventBridge,
57180
57180
  shutdownPipelineEventBridge
57181
57181
  };
57182
- //# sourceMappingURL=chunk-HXITPFTR.js.map
57182
+ //# sourceMappingURL=chunk-W6VHVDZM.js.map
@@ -25,10 +25,10 @@ import {
25
25
  toolSuccessStructured,
26
26
  withProgressHeartbeat,
27
27
  wrapToolWithTimeout
28
- } from "./chunk-BWP3RTR2.js";
28
+ } from "./chunk-VCLNGU3S.js";
29
29
  import {
30
30
  VERSION
31
- } from "./chunk-UURJGJTW.js";
31
+ } from "./chunk-H3PRTTXF.js";
32
32
  import {
33
33
  UNRESOLVED_MODEL_ID,
34
34
  assessPanelIndependence,
@@ -8726,6 +8726,7 @@ export {
8726
8726
  createCorrelationTracker,
8727
8727
  seatFallbacks,
8728
8728
  panelDiversityOf,
8729
+ VoteRecordPrBindingSchema,
8729
8730
  VotingStrategySchema,
8730
8731
  ErrorPolicySchema,
8731
8732
  VoteThresholdSchema,
@@ -8747,4 +8748,4 @@ export {
8747
8748
  CONSENSUS_VOTE_TOOL_SCHEMA,
8748
8749
  registerConsensusVoteTool
8749
8750
  };
8750
- //# sourceMappingURL=chunk-MO6FSEFJ.js.map
8751
+ //# sourceMappingURL=chunk-XU72ZQ5Z.js.map
package/dist/cli.d.ts CHANGED
@@ -1,6 +1,76 @@
1
1
  #!/usr/bin/env node
2
- import { C as CliNameLiteral, L as VoteThreshold, E as ErrorPolicy, N as NoQuorumPolicy } from './consensus-vote-types-cDFfyFTQ.js';
3
- import 'zod';
2
+ import { C as CliNameLiteral, L as VoteThreshold, o as VotingStrategy, E as ErrorPolicy, N as NoQuorumPolicy } from './consensus-vote-types-cDFfyFTQ.js';
3
+ import { z } from 'zod';
4
+
5
+ /**
6
+ * nexus-agents/audit - Authentic Vote Record (#3897, model revised #3927)
7
+ *
8
+ * A committed, append-only, tamper-EVIDENT record of a completed
9
+ * `consensus_vote`, persisted at vote time so the authority-ladder promotion
10
+ * gate (`scripts/check-authority-tier-drift.ts`, #3895) can rest authenticity
11
+ * on a tamper-evident record set instead of on hand-transcribed YAML.
12
+ *
13
+ * MODEL: TAMPER-EVIDENT RECORD SET + MONOTONIC SEQUENCE (NOT a linear hash
14
+ * chain). #3927 (design vote 7-0, Option B). The original #3897 design was a
15
+ * LINEAR HASH CHAIN: each record's `hash` folded in the prior record's hash, so
16
+ * the order of file lines was load-bearing. That model cannot survive a
17
+ * concurrent-branch git merge — two branches that each append a record from the
18
+ * same tip produce two records claiming the same `previousHash`, and any
19
+ * merge-concatenation breaks the back-link check. The revised model treats the
20
+ * ledger as an UNORDERED SET of self-hashed records plus a monotonic `sequence`
21
+ * number: each record's hash is POSITION-INDEPENDENT (covers `sequence` but NOT
22
+ * `previousHash`), so it is stable across merges and reorders. `previousHash`
23
+ * is retained ADVISORILY for audit texture but does NOT participate in
24
+ * verification. Omission is detected via SEQUENCE GAPS; concurrent forks (two
25
+ * records sharing a sequence) are a BENIGN signal, not a failure.
26
+ *
27
+ * KNOWN GAP IN OMISSION DETECTION (#4011): sequence-gap detection only catches an
28
+ * omission that leaves a HOLE in the `0..maxSeq` run. It does NOT catch the
29
+ * deletion of a FORK PARTNER — when a sequence is shared by ≥2 records and one is
30
+ * removed, the surviving partner still occupies that sequence, so no gap appears
31
+ * and verification still returns `ok`. So a concurrent fork that resolved
32
+ * `approved` + `rejected` can have its `rejected` partner silently dropped. This
33
+ * is consistent with the residual-trust boundary (records are author-typed and
34
+ * NOT yet cryptographically signed — signing is #3927 item 4): a commit-access
35
+ * actor could equally have just never written the rejecting record, so this grants
36
+ * no new capability. Closing it (cross-checking `forks`/`recordCount`, or
37
+ * requiring fork partners to be co-present) is only meaningful once signing raises
38
+ * the overall bar, and folds into #3927 item 4. See the audit-hash-chain threat
39
+ * model for the disclosed boundary.
40
+ *
41
+ * WHY A DEDICATED PAYLOAD-COVERING HASH (and not the audit-event head hash).
42
+ * The audit-event chain (`computeEventHash` in audit-logger.ts) hashes only the
43
+ * stable HEAD fields (id/timestamp/category/action/outcome/actor/previousHash)
44
+ * and intentionally NOT `metadata` — so riding a tier-transition-style metadata
45
+ * payload would leave the vote `decision`/`approvalPercentage` OUTSIDE the
46
+ * hash: an attacker could flip `rejected`→`approved` in the metadata without
47
+ * breaking any hash. That defeats the whole point of #3897. This record instead
48
+ * folds EVERY authenticity-bearing field — the proposal content hash, the
49
+ * decision, the approval percentage, the vote counts, the per-voter summary,
50
+ * and the `sequence` — into the self-hash, so editing any of them is detected
51
+ * as a `hash_mismatch`. This is the tamper-evidence MVP; cryptographic
52
+ * signing/provenance (binding the record to a key) is DEFERRED (#3897 follow-up).
53
+ *
54
+ * NOTE: the separate audit-event/tier-transition chain (`audit-logger.ts`) IS
55
+ * still a real linear hash chain — it has a single-writer runtime and never
56
+ * merges concurrent branches, so the chain model holds there. Only THIS ledger
57
+ * (a multi-branch committable artifact) was converted to a record set.
58
+ *
59
+ * @module audit/vote-record
60
+ */
61
+
62
+ /**
63
+ * The `{pr, headSha}` binding of a PR-ratification vote (#5130 step 1, schema
64
+ * 1.10). `pr` is the PR number the panel ratified; `headSha` is the full head
65
+ * commit the panel saw. Exported for the `consensus_vote` input schema and the
66
+ * caller-commits append script, so producer, record and script validate the
67
+ * same shape.
68
+ */
69
+ declare const VoteRecordPrBindingSchema: z.ZodObject<{
70
+ pr: z.ZodNumber;
71
+ headSha: z.ZodString;
72
+ }, z.core.$strict>;
73
+ type VoteRecordPrBinding = z.infer<typeof VoteRecordPrBindingSchema>;
4
74
 
5
75
  /**
6
76
  * nexus-agents/cli - Mode Detector
@@ -74,7 +144,12 @@ interface ParsedCliArgs {
74
144
  createIssue: boolean;
75
145
  fix: boolean;
76
146
  proposal?: string;
147
+ /** Legacy spelling of the bar; `strategy` wins when both are given (#6227). */
77
148
  threshold?: VoteThreshold;
149
+ /** #6227 — `--strategy`, the tool's own enum, passed to the engine as the MCP tool passes it. */
150
+ strategy?: VotingStrategy;
151
+ /** #6227 — `--ratifies-pr <n>@<sha>`, already parsed into the record's binding shape. */
152
+ ratifiesPr?: VoteRecordPrBinding;
78
153
  quick: boolean;
79
154
  timeoutMs?: number;
80
155
  /** #2630 — see `applyErrorPolicy`. */
package/dist/cli.js CHANGED
@@ -157,7 +157,7 @@ import {
157
157
  validateNexusEnv,
158
158
  validateWorkflow,
159
159
  wrapInMarkdownFence
160
- } from "./chunk-HXITPFTR.js";
160
+ } from "./chunk-W6VHVDZM.js";
161
161
  import "./chunk-MHXSHTHG.js";
162
162
  import "./chunk-4GDMHCKX.js";
163
163
  import "./chunk-M7DUOIAK.js";
@@ -177,7 +177,7 @@ import {
177
177
  doctorCommand,
178
178
  initDataDirectories,
179
179
  runDoctor
180
- } from "./chunk-M2ZQXDSO.js";
180
+ } from "./chunk-IJMAA7MV.js";
181
181
  import "./chunk-PMWQSCYE.js";
182
182
  import {
183
183
  buildOpenAICompatAdapters,
@@ -192,7 +192,9 @@ import {
192
192
  ErrorPolicySchema,
193
193
  JOB_RECORD_RETENTION_MS,
194
194
  VOTER_ROLES,
195
+ VoteRecordPrBindingSchema,
195
196
  VoteThresholdSchema,
197
+ VotingStrategySchema,
196
198
  executeVoting,
197
199
  mapOutcomeToDecision,
198
200
  panelDiversityOf,
@@ -201,7 +203,7 @@ import {
201
203
  registerConsensusVoteTool,
202
204
  seatFallbacks,
203
205
  toRecordDecision
204
- } from "./chunk-MO6FSEFJ.js";
206
+ } from "./chunk-XU72ZQ5Z.js";
205
207
  import {
206
208
  loadUsageEvents,
207
209
  rollupByModel
@@ -241,18 +243,18 @@ import {
241
243
  registerImprovementReviewTool,
242
244
  runImprovementReview,
243
245
  scanForSecrets
244
- } from "./chunk-5W55WXLY.js";
246
+ } from "./chunk-3KOCMFOK.js";
245
247
  import {
246
248
  createDefaultPolicyFirewall,
247
249
  setGlobalPolicyFirewall,
248
250
  setSecureHandlerAuditLogger,
249
251
  stagePolicyFirewallForRollout
250
- } from "./chunk-BWP3RTR2.js";
252
+ } from "./chunk-VCLNGU3S.js";
251
253
  import {
252
254
  NODE_ENGINE_RANGE,
253
255
  VERSION,
254
256
  isNodeVersionSupported
255
- } from "./chunk-UURJGJTW.js";
257
+ } from "./chunk-H3PRTTXF.js";
256
258
  import "./chunk-VZSMNIRN.js";
257
259
  import {
258
260
  claimGlobalRegistry,
@@ -3910,6 +3912,16 @@ var PARSE_ARGS_CONFIG = {
3910
3912
  threshold: {
3911
3913
  type: "string"
3912
3914
  },
3915
+ // #6227 — the bar as the tool spells it. `threshold` is the legacy spelling;
3916
+ // the engine's `resolveStrategy` lets `strategy` win when both are given.
3917
+ strategy: {
3918
+ type: "string"
3919
+ },
3920
+ // #6227 — `<pr>@<40-hex sha>`: binds the record to a governor-path PR for
3921
+ // `scripts/append-ratification-record.ts`. Validated in `buildVoteOptions`.
3922
+ "ratifies-pr": {
3923
+ type: "string"
3924
+ },
3913
3925
  quick: {
3914
3926
  type: "boolean",
3915
3927
  short: "q",
@@ -7476,6 +7488,32 @@ function auditLineFor(outcome) {
7476
7488
  return `${colors.yellow}Vote NOT recorded to the audit chain: ${outcome.detail}${colors.reset}
7477
7489
  `;
7478
7490
  }
7491
+ function prBindingLine(outcome, binding) {
7492
+ const target = `PR ${String(binding.pr)} @ ${binding.headSha}`;
7493
+ if (outcome.persisted) {
7494
+ return `${colors.dim}record ${outcome.record.id} bound to ${target}${colors.reset}
7495
+ `;
7496
+ }
7497
+ return `${colors.yellow}Binding to ${target} NOT recorded \u2014 no record was written, so there is nothing for append-ratification-record.ts to copy${colors.reset}
7498
+ `;
7499
+ }
7500
+ var GOVERNOR_BAR = { strategy: "supermajority", errorPolicy: "absolute_quorum" };
7501
+ function governorBarNotice(ran) {
7502
+ if (ran.strategy === GOVERNOR_BAR.strategy && ran.errorPolicy === GOVERNOR_BAR.errorPolicy) {
7503
+ return void 0;
7504
+ }
7505
+ return `${colors.yellow}Notice: the governor bar is --strategy ${GOVERNOR_BAR.strategy} --error-policy ${GOVERNOR_BAR.errorPolicy}; this vote ran at ${ran.strategy} / ${ran.errorPolicy ?? "unrecorded"} and was recorded as run \u2014 the ledger gate judges it, not the CLI${colors.reset}
7506
+ `;
7507
+ }
7508
+ function persistLines(outcome, binding, ran) {
7509
+ if (binding === void 0) return [auditLineFor(outcome)];
7510
+ const notice = governorBarNotice(ran);
7511
+ return [
7512
+ auditLineFor(outcome),
7513
+ prBindingLine(outcome, binding),
7514
+ ...notice === void 0 ? [] : [notice]
7515
+ ];
7516
+ }
7479
7517
 
7480
7518
  // src/cli/vote-command.ts
7481
7519
  function generateVoteHash(role, vote) {
@@ -7655,6 +7693,8 @@ function toVoteInput(options, quickMode) {
7655
7693
  quickMode,
7656
7694
  simulateVotes: options.dryRun === true,
7657
7695
  ...options.threshold !== void 0 && { threshold: options.threshold },
7696
+ // #6227: both bar spellings go through; `resolveStrategy` lets `strategy` win.
7697
+ ...options.strategy !== void 0 && { strategy: options.strategy },
7658
7698
  ...options.errorPolicy !== void 0 && { errorPolicy: options.errorPolicy }
7659
7699
  };
7660
7700
  }
@@ -7752,26 +7792,24 @@ function exitCodeForDecision(decision, policy) {
7752
7792
  }
7753
7793
  function persistToAuditChain(options, result) {
7754
7794
  if (options.dryRun === true) return;
7755
- writeLine(
7756
- auditLineFor(
7757
- recordAuthenticVote({
7758
- proposal: result.proposal,
7759
- strategy: result.strategy,
7760
- result: result.result,
7761
- votes: result.votes,
7762
- // #6049: the CLI path had the declared options all along and did not
7763
- // pass them, so its records lost the option fields whenever no
7764
- // selection was parseable -- the same defect as the MCP path.
7765
- declaredOptions: options.options,
7766
- // A vote an error policy voided is not a rejection. Without this the
7767
- // chain records `rejected` while the CLI exits `no_quorum` (#4953).
7768
- errorVoided: result.policyReason !== void 0,
7769
- resolvedDecision: toRecordDecision(result.decision),
7770
- // #6211: the policy the panel ran under, as `executeVoting` resolved it.
7771
- errorPolicy: result.errorPolicy
7772
- })
7773
- )
7774
- );
7795
+ const outcome = recordAuthenticVote({
7796
+ proposal: result.proposal,
7797
+ strategy: result.strategy,
7798
+ result: result.result,
7799
+ votes: result.votes,
7800
+ // #6049: the CLI path had the declared options all along and did not
7801
+ // pass them, so its records lost the option fields whenever no
7802
+ // selection was parseable -- the same defect as the MCP path.
7803
+ declaredOptions: options.options,
7804
+ // A vote an error policy voided is not a rejection. Without this the
7805
+ // chain records `rejected` while the CLI exits `no_quorum` (#4953).
7806
+ errorVoided: result.policyReason !== void 0,
7807
+ resolvedDecision: toRecordDecision(result.decision),
7808
+ // #6211: the policy the panel ran under, as `executeVoting` resolved it.
7809
+ errorPolicy: result.errorPolicy,
7810
+ ratifiesPr: options.ratifiesPr
7811
+ });
7812
+ for (const line of persistLines(outcome, options.ratifiesPr, result)) writeLine(line);
7775
7813
  }
7776
7814
  async function voteCommand(options) {
7777
7815
  writeLine(`
@@ -19509,7 +19547,7 @@ function startImprovementReviewScheduler(options) {
19509
19547
  let running = false;
19510
19548
  const runOnce = async () => {
19511
19549
  try {
19512
- const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-MTQWL4BT.js");
19550
+ const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-TTJVCUXN.js");
19513
19551
  const input = ImprovementReviewInputSchema2.parse({ fileIssues });
19514
19552
  const result = await runImprovementReview2(input, { logger: logger22 });
19515
19553
  logger22.info("Scheduled improvement_review complete", {
@@ -22211,11 +22249,23 @@ var VOTE_HELP = {
22211
22249
  'nexus-agents vote -p "Migrate to PostgreSQL" --threshold supermajority',
22212
22250
  'nexus-agents vote -p "Pick a cache" --option "Redis" --option "in-process LRU"',
22213
22251
  'nexus-agents vote -p "Quick decision" --quick',
22214
- 'nexus-agents vote -p "Test idea" --dry-run'
22252
+ 'nexus-agents vote -p "Test idea" --dry-run',
22253
+ 'nexus-agents vote -p "Ratify PR #6227 at <sha>" --strategy supermajority --error-policy absolute_quorum --ratifies-pr 6227@<sha>'
22215
22254
  ],
22216
22255
  flags: [
22217
22256
  { flag: "-p, --proposal <text>", description: "Proposal text to vote on (required)" },
22218
- { flag: "--threshold <t>", description: "Threshold: majority, supermajority, unanimous" },
22257
+ {
22258
+ flag: "--strategy <s>",
22259
+ description: "The bar, as the consensus_vote tool spells it: simple_majority (default) | supermajority | unanimous | proof_of_learning | higher_order | opinion_wise. Wins over --threshold when both are given (#6227)"
22260
+ },
22261
+ {
22262
+ flag: "--threshold <t>",
22263
+ description: "Legacy spelling of the bar: majority | supermajority | unanimous. --strategy wins when both are given"
22264
+ },
22265
+ {
22266
+ flag: "--ratifies-pr <n>@<sha>",
22267
+ description: "Bind the audit record to a governor-path PR at its full 40-hex lowercase head sha (#6227, #5130), e.g. 6227@0123\u2026; prints `record <id> bound to PR n @ sha` for scripts/append-ratification-record.ts --record-id. The governor bar is --strategy supermajority --error-policy absolute_quorum; a vote below it is still recorded, with a notice"
22268
+ },
22219
22269
  {
22220
22270
  flag: "--option <text>",
22221
22271
  description: "Named alternative (repeatable, 2-10). Records WHICH option won, not just approval"
@@ -22797,6 +22847,10 @@ function buildVoteCommandOptions(args) {
22797
22847
  proposal: args.options.proposal ?? "",
22798
22848
  ...args.options.options !== void 0 && { options: args.options.options },
22799
22849
  ...validThreshold !== void 0 && { threshold: validThreshold },
22850
+ // #6227: both already validated by the parser (`parseStrategy`,
22851
+ // `parseRatifiesPr` refuse rather than drop), so they are carried as-is.
22852
+ ...args.options.strategy !== void 0 && { strategy: args.options.strategy },
22853
+ ...args.options.ratifiesPr !== void 0 && { ratifiesPr: args.options.ratifiesPr },
22800
22854
  ...validErrorPolicy !== void 0 && { errorPolicy: validErrorPolicy },
22801
22855
  ...args.options.onNoQuorum !== void 0 && { onNoQuorum: args.options.onNoQuorum },
22802
22856
  ...args.options.timeoutMs !== void 0 && { timeoutMs: args.options.timeoutMs },
@@ -28174,6 +28228,51 @@ function isDirectRun(argv1) {
28174
28228
  return DIRECT_RUN_SUFFIXES.some((suffix) => argv1.endsWith(suffix));
28175
28229
  }
28176
28230
 
28231
+ // src/cli/vote-bar-flags.ts
28232
+ function parseThreshold(value) {
28233
+ if (value === void 0) return void 0;
28234
+ const parsed = VoteThresholdSchema.safeParse(value);
28235
+ return parsed.success ? parsed.data : void 0;
28236
+ }
28237
+ function parseStrategy(value) {
28238
+ if (value === void 0) return void 0;
28239
+ const parsed = VotingStrategySchema.safeParse(value);
28240
+ if (!parsed.success) {
28241
+ throw new Error(
28242
+ `--strategy must be one of ${VotingStrategySchema.options.join(", ")}; got '${value}'`
28243
+ );
28244
+ }
28245
+ return parsed.data;
28246
+ }
28247
+ var RATIFIES_PR_FORM = "<number>@<40-hex-lowercase-sha>";
28248
+ function parseRatifiesPr(value) {
28249
+ if (value === void 0) return void 0;
28250
+ const expected = `--ratifies-pr expects ${RATIFIES_PR_FORM}; got '${value}'`;
28251
+ const at = value.indexOf("@");
28252
+ if (at === -1) throw new Error(`${expected} (no '@')`);
28253
+ const prText = value.slice(0, at);
28254
+ const headSha = value.slice(at + 1);
28255
+ if (!/^\d+$/.test(prText)) {
28256
+ throw new Error(`${expected} (the PR number must be a positive integer)`);
28257
+ }
28258
+ const parsed = VoteRecordPrBindingSchema.safeParse({ pr: Number(prText), headSha });
28259
+ if (!parsed.success) {
28260
+ const detail = parsed.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
28261
+ throw new Error(`${expected} (${detail})`);
28262
+ }
28263
+ return parsed.data;
28264
+ }
28265
+ function parseVoteBarFlags(values) {
28266
+ const threshold = parseThreshold(values.threshold);
28267
+ const strategy = parseStrategy(values.strategy);
28268
+ const ratifiesPr = parseRatifiesPr(values["ratifies-pr"]);
28269
+ return {
28270
+ ...threshold !== void 0 && { threshold },
28271
+ ...strategy !== void 0 && { strategy },
28272
+ ...ratifiesPr !== void 0 && { ratifiesPr }
28273
+ };
28274
+ }
28275
+
28177
28276
  // src/cli.ts
28178
28277
  function determineCommand(options, positionals) {
28179
28278
  const firstArg = positionals[0];
@@ -28217,11 +28316,6 @@ function buildOrchestrateOptions(values) {
28217
28316
  ...maxSteps !== void 0 && { maxSteps }
28218
28317
  };
28219
28318
  }
28220
- function parseThreshold(value) {
28221
- if (value === void 0) return void 0;
28222
- const parsed = VoteThresholdSchema.safeParse(value);
28223
- return parsed.success ? parsed.data : void 0;
28224
- }
28225
28319
  function parseErrorPolicy(value) {
28226
28320
  if (value === void 0) return void 0;
28227
28321
  const parsed = ErrorPolicySchema.safeParse(value);
@@ -28231,7 +28325,6 @@ function parseNoQuorumPolicy(value) {
28231
28325
  return value === "fail" || value === "exit2" || value === "retry" ? value : void 0;
28232
28326
  }
28233
28327
  function buildVoteOptions(values) {
28234
- const threshold = parseThreshold(values.threshold);
28235
28328
  const timeoutSec = parseNumericOption(values.timeout);
28236
28329
  const timeoutMs = timeoutSec !== void 0 ? timeoutSec * 1e3 : void 0;
28237
28330
  const errorPolicy = parseErrorPolicy(values["error-policy"]);
@@ -28240,7 +28333,9 @@ function buildVoteOptions(values) {
28240
28333
  return {
28241
28334
  ...values.proposal !== void 0 && { proposal: values.proposal },
28242
28335
  ...options !== void 0 && options.length > 0 && { options },
28243
- ...threshold !== void 0 && { threshold },
28336
+ // #6227: `--threshold` (legacy), `--strategy` and `--ratifies-pr`; the
28337
+ // latter two REFUSE an invalid value (see `vote-bar-flags.ts`).
28338
+ ...parseVoteBarFlags(values),
28244
28339
  ...timeoutMs !== void 0 && { timeoutMs },
28245
28340
  ...errorPolicy !== void 0 && { errorPolicy },
28246
28341
  ...onNoQuorum !== void 0 && { onNoQuorum },