nexus-agents 2.134.0 → 2.136.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.
Files changed (153) hide show
  1. package/dist/{child-mcp-config-TWHH63UK.js → child-mcp-config-TM6OCARU.js} +4 -3
  2. package/dist/{child-mcp-config-TWHH63UK.js.map → child-mcp-config-TM6OCARU.js.map} +1 -1
  3. package/dist/{chunk-E64SZTEP.js → chunk-257QMFTM.js} +3 -3
  4. package/dist/{chunk-PQHVC4BD.js → chunk-2XRPKJKX.js} +23 -12
  5. package/dist/chunk-2XRPKJKX.js.map +1 -0
  6. package/dist/{chunk-FUJ3XR7T.js → chunk-3AAJWZCR.js} +4 -4
  7. package/dist/{chunk-Z6DXZ6AS.js → chunk-3JSDOBOA.js} +2 -2
  8. package/dist/{chunk-FPMQ2JAK.js → chunk-3QH2KWLH.js} +2 -2
  9. package/dist/{chunk-7TQZR5VU.js → chunk-3WBEEYCS.js} +116 -22
  10. package/dist/chunk-3WBEEYCS.js.map +1 -0
  11. package/dist/{chunk-UDB5NHJI.js → chunk-4GVPON4W.js} +3 -3
  12. package/dist/{chunk-QZUT22LP.js → chunk-5546JU53.js} +8 -8
  13. package/dist/chunk-5SXGPX34.js +44 -0
  14. package/dist/chunk-5SXGPX34.js.map +1 -0
  15. package/dist/{chunk-7GSYICTL.js → chunk-66TXNH4S.js} +14 -12
  16. package/dist/{chunk-7GSYICTL.js.map → chunk-66TXNH4S.js.map} +1 -1
  17. package/dist/{chunk-76R5ES6Z.js → chunk-6JOXXQK2.js} +191 -132
  18. package/dist/chunk-6JOXXQK2.js.map +1 -0
  19. package/dist/{chunk-ZMDOGN33.js → chunk-7E5UXA4U.js} +2 -2
  20. package/dist/{chunk-F74ZGHAP.js → chunk-7G63H7ZT.js} +2 -2
  21. package/dist/{chunk-FVSZLVMR.js → chunk-CQDGPGTL.js} +3 -3
  22. package/dist/{chunk-33MFMXBQ.js → chunk-ESP6U3LW.js} +13 -81
  23. package/dist/chunk-ESP6U3LW.js.map +1 -0
  24. package/dist/{chunk-MY52DFXC.js → chunk-FHFEC2XM.js} +2 -2
  25. package/dist/{chunk-ORQAFTAZ.js → chunk-FIQSOSQU.js} +2 -2
  26. package/dist/{chunk-EHLJLIHS.js → chunk-FSUZIIOJ.js} +2 -2
  27. package/dist/{chunk-3EYXPV5F.js → chunk-GWOXPCIF.js} +13 -13
  28. package/dist/{chunk-WYJJUF6N.js → chunk-HMZT2SJK.js} +4 -4
  29. package/dist/{chunk-OCKZ6F5O.js → chunk-JK4L2TQ6.js} +3 -3
  30. package/dist/{chunk-6UCWR3DS.js → chunk-JVZ7FGWR.js} +3 -3
  31. package/dist/{chunk-PFBV5FCT.js → chunk-KOVTOPEQ.js} +2 -2
  32. package/dist/{chunk-GZ4NF4ZW.js → chunk-L4QFWOOQ.js} +63 -92
  33. package/dist/chunk-L4QFWOOQ.js.map +1 -0
  34. package/dist/{chunk-6LMZ7HFU.js → chunk-LCSGGLZZ.js} +2 -2
  35. package/dist/{chunk-IWQH6TP7.js → chunk-MTE7THMR.js} +6 -6
  36. package/dist/{chunk-DLUFDKPA.js → chunk-N67LHY47.js} +89 -32
  37. package/dist/chunk-N67LHY47.js.map +1 -0
  38. package/dist/{chunk-DBDWMHUL.js → chunk-OCJEYHUQ.js} +18 -10
  39. package/dist/chunk-OCJEYHUQ.js.map +1 -0
  40. package/dist/chunk-UGAKYSDO.js +92 -0
  41. package/dist/chunk-UGAKYSDO.js.map +1 -0
  42. package/dist/{chunk-VI7LELES.js → chunk-UH3F4RZB.js} +7 -7
  43. package/dist/{chunk-COJOUIO2.js → chunk-VN3CKPEF.js} +3 -3
  44. package/dist/{chunk-FSFF7EFR.js → chunk-VVBKPRLI.js} +2 -2
  45. package/dist/{chunk-OU2NQVKD.js → chunk-VY4FZNZA.js} +2 -2
  46. package/dist/{chunk-BTYYZ6VU.js → chunk-WOE5J5M6.js} +4 -4
  47. package/dist/{chunk-B26FGLIJ.js → chunk-ZHCEOIEQ.js} +2 -2
  48. package/dist/{chunk-WFKVUZ3O.js → chunk-ZII5MDUO.js} +2 -2
  49. package/dist/{chunk-CLRSNWRQ.js → chunk-ZLENFXL5.js} +4 -4
  50. package/dist/cli-circuit-breaker-HFFMCA43.js +14 -0
  51. package/dist/cli.d.ts +1 -1
  52. package/dist/cli.js +68 -66
  53. package/dist/cli.js.map +1 -1
  54. package/dist/{composite-router-E6FXXMMR.js → composite-router-PS42433A.js} +4 -3
  55. package/dist/consensus-vote-K2SHY4TC.js +39 -0
  56. package/dist/{consensus-vote-types-CYBHW8vY.d.ts → consensus-vote-types-Dx4pf3YW.d.ts} +16 -0
  57. package/dist/{context-retriever-I4NEOUEV.js → context-retriever-NIFXFYPQ.js} +12 -10
  58. package/dist/{dist-C4457XNQ.js → dist-KGTVHDVC.js} +4 -2
  59. package/dist/doctor-deep-VQQNT7VN.js +13 -0
  60. package/dist/{expert-bridge-GMB5IHHF.js → expert-bridge-NY6FAFQH.js} +6 -5
  61. package/dist/factory-6A26HIWS.js +15 -0
  62. package/dist/factory-GGSACEWN.js +22 -0
  63. package/dist/{improvement-review-77BKIQGN.js → improvement-review-JDSRWFHM.js} +8 -5
  64. package/dist/index.d.ts +27 -20
  65. package/dist/index.js +64 -62
  66. package/dist/index.js.map +1 -1
  67. package/dist/{init-opencode-4H2VPN23.js → init-opencode-C7U6ZQK3.js} +8 -7
  68. package/dist/{init-opencode-4H2VPN23.js.map → init-opencode-C7U6ZQK3.js.map} +1 -1
  69. package/dist/issue-triage-7RN74LBU.js +17 -0
  70. package/dist/{learning-persistence-2KO4CXNL.js → learning-persistence-EHTHKWR5.js} +3 -2
  71. package/dist/{pr-reviewer-helpers-F3SHCHNV.js → pr-reviewer-helpers-D47TVXFX.js} +6 -5
  72. package/dist/{registry-command-VFCSMHME.js → registry-command-PVC47NSQ.js} +4 -3
  73. package/dist/{registry-command-VFCSMHME.js.map → registry-command-PVC47NSQ.js.map} +1 -1
  74. package/dist/{repo-security-plan-U2ZIFW53.js → repo-security-plan-76IXMJNC.js} +5 -4
  75. package/dist/research-helpers-synthesize-WH4IC36H.js +15 -0
  76. package/dist/{routing-memory-VVLJL3MG.js → routing-memory-RAYIYIUP.js} +4 -3
  77. package/dist/{session-memory-GMQYZLJE.js → session-memory-WZCS7WDH.js} +5 -4
  78. package/dist/{setup-command-IMAX6EAO.js → setup-command-O62DVQ2U.js} +13 -12
  79. package/dist/setup-config-KEBEUMC3.js +11 -0
  80. package/dist/{setup-custom-api-NJGCRIRO.js → setup-custom-api-2PQP6UOT.js} +5 -4
  81. package/dist/{setup-custom-api-NJGCRIRO.js.map → setup-custom-api-2PQP6UOT.js.map} +1 -1
  82. package/dist/tool-memory-RAQWOUXV.js +22 -0
  83. package/dist/tool-memory-registry-adapters-Y4EGADHN.js +12 -0
  84. package/dist/unified-registry-L5PGLSEI.js +25 -0
  85. package/dist/{weather-report-OU65NJS3.js → weather-report-TEBEALS7.js} +4 -3
  86. package/dist/weather-report-TEBEALS7.js.map +1 -0
  87. package/package.json +2 -2
  88. package/dist/chunk-33MFMXBQ.js.map +0 -1
  89. package/dist/chunk-76R5ES6Z.js.map +0 -1
  90. package/dist/chunk-7TQZR5VU.js.map +0 -1
  91. package/dist/chunk-DBDWMHUL.js.map +0 -1
  92. package/dist/chunk-DLUFDKPA.js.map +0 -1
  93. package/dist/chunk-GZ4NF4ZW.js.map +0 -1
  94. package/dist/chunk-PQHVC4BD.js.map +0 -1
  95. package/dist/cli-circuit-breaker-VXBDCAD7.js +0 -13
  96. package/dist/consensus-vote-R6X5IL57.js +0 -37
  97. package/dist/doctor-deep-CZXN4YD6.js +0 -12
  98. package/dist/factory-WR62MEIJ.js +0 -14
  99. package/dist/factory-ZBQGA373.js +0 -21
  100. package/dist/issue-triage-NJB6SL4S.js +0 -16
  101. package/dist/research-helpers-synthesize-5TLNHT3I.js +0 -14
  102. package/dist/setup-config-2ZSJ3HNE.js +0 -10
  103. package/dist/tool-memory-TSYJXGOV.js +0 -20
  104. package/dist/unified-registry-IMAL3SY6.js +0 -24
  105. /package/dist/{chunk-E64SZTEP.js.map → chunk-257QMFTM.js.map} +0 -0
  106. /package/dist/{chunk-FUJ3XR7T.js.map → chunk-3AAJWZCR.js.map} +0 -0
  107. /package/dist/{chunk-Z6DXZ6AS.js.map → chunk-3JSDOBOA.js.map} +0 -0
  108. /package/dist/{chunk-FPMQ2JAK.js.map → chunk-3QH2KWLH.js.map} +0 -0
  109. /package/dist/{chunk-UDB5NHJI.js.map → chunk-4GVPON4W.js.map} +0 -0
  110. /package/dist/{chunk-QZUT22LP.js.map → chunk-5546JU53.js.map} +0 -0
  111. /package/dist/{chunk-ZMDOGN33.js.map → chunk-7E5UXA4U.js.map} +0 -0
  112. /package/dist/{chunk-F74ZGHAP.js.map → chunk-7G63H7ZT.js.map} +0 -0
  113. /package/dist/{chunk-FVSZLVMR.js.map → chunk-CQDGPGTL.js.map} +0 -0
  114. /package/dist/{chunk-MY52DFXC.js.map → chunk-FHFEC2XM.js.map} +0 -0
  115. /package/dist/{chunk-ORQAFTAZ.js.map → chunk-FIQSOSQU.js.map} +0 -0
  116. /package/dist/{chunk-EHLJLIHS.js.map → chunk-FSUZIIOJ.js.map} +0 -0
  117. /package/dist/{chunk-3EYXPV5F.js.map → chunk-GWOXPCIF.js.map} +0 -0
  118. /package/dist/{chunk-WYJJUF6N.js.map → chunk-HMZT2SJK.js.map} +0 -0
  119. /package/dist/{chunk-OCKZ6F5O.js.map → chunk-JK4L2TQ6.js.map} +0 -0
  120. /package/dist/{chunk-6UCWR3DS.js.map → chunk-JVZ7FGWR.js.map} +0 -0
  121. /package/dist/{chunk-PFBV5FCT.js.map → chunk-KOVTOPEQ.js.map} +0 -0
  122. /package/dist/{chunk-6LMZ7HFU.js.map → chunk-LCSGGLZZ.js.map} +0 -0
  123. /package/dist/{chunk-IWQH6TP7.js.map → chunk-MTE7THMR.js.map} +0 -0
  124. /package/dist/{chunk-VI7LELES.js.map → chunk-UH3F4RZB.js.map} +0 -0
  125. /package/dist/{chunk-COJOUIO2.js.map → chunk-VN3CKPEF.js.map} +0 -0
  126. /package/dist/{chunk-FSFF7EFR.js.map → chunk-VVBKPRLI.js.map} +0 -0
  127. /package/dist/{chunk-OU2NQVKD.js.map → chunk-VY4FZNZA.js.map} +0 -0
  128. /package/dist/{chunk-BTYYZ6VU.js.map → chunk-WOE5J5M6.js.map} +0 -0
  129. /package/dist/{chunk-B26FGLIJ.js.map → chunk-ZHCEOIEQ.js.map} +0 -0
  130. /package/dist/{chunk-WFKVUZ3O.js.map → chunk-ZII5MDUO.js.map} +0 -0
  131. /package/dist/{chunk-CLRSNWRQ.js.map → chunk-ZLENFXL5.js.map} +0 -0
  132. /package/dist/{cli-circuit-breaker-VXBDCAD7.js.map → cli-circuit-breaker-HFFMCA43.js.map} +0 -0
  133. /package/dist/{composite-router-E6FXXMMR.js.map → composite-router-PS42433A.js.map} +0 -0
  134. /package/dist/{consensus-vote-R6X5IL57.js.map → consensus-vote-K2SHY4TC.js.map} +0 -0
  135. /package/dist/{context-retriever-I4NEOUEV.js.map → context-retriever-NIFXFYPQ.js.map} +0 -0
  136. /package/dist/{dist-C4457XNQ.js.map → dist-KGTVHDVC.js.map} +0 -0
  137. /package/dist/{doctor-deep-CZXN4YD6.js.map → doctor-deep-VQQNT7VN.js.map} +0 -0
  138. /package/dist/{expert-bridge-GMB5IHHF.js.map → expert-bridge-NY6FAFQH.js.map} +0 -0
  139. /package/dist/{factory-WR62MEIJ.js.map → factory-6A26HIWS.js.map} +0 -0
  140. /package/dist/{factory-ZBQGA373.js.map → factory-GGSACEWN.js.map} +0 -0
  141. /package/dist/{improvement-review-77BKIQGN.js.map → improvement-review-JDSRWFHM.js.map} +0 -0
  142. /package/dist/{issue-triage-NJB6SL4S.js.map → issue-triage-7RN74LBU.js.map} +0 -0
  143. /package/dist/{learning-persistence-2KO4CXNL.js.map → learning-persistence-EHTHKWR5.js.map} +0 -0
  144. /package/dist/{pr-reviewer-helpers-F3SHCHNV.js.map → pr-reviewer-helpers-D47TVXFX.js.map} +0 -0
  145. /package/dist/{repo-security-plan-U2ZIFW53.js.map → repo-security-plan-76IXMJNC.js.map} +0 -0
  146. /package/dist/{research-helpers-synthesize-5TLNHT3I.js.map → research-helpers-synthesize-WH4IC36H.js.map} +0 -0
  147. /package/dist/{routing-memory-VVLJL3MG.js.map → routing-memory-RAYIYIUP.js.map} +0 -0
  148. /package/dist/{session-memory-GMQYZLJE.js.map → session-memory-WZCS7WDH.js.map} +0 -0
  149. /package/dist/{setup-command-IMAX6EAO.js.map → setup-command-O62DVQ2U.js.map} +0 -0
  150. /package/dist/{setup-config-2ZSJ3HNE.js.map → setup-config-KEBEUMC3.js.map} +0 -0
  151. /package/dist/{tool-memory-TSYJXGOV.js.map → tool-memory-RAQWOUXV.js.map} +0 -0
  152. /package/dist/{unified-registry-IMAL3SY6.js.map → tool-memory-registry-adapters-Y4EGADHN.js.map} +0 -0
  153. /package/dist/{weather-report-OU65NJS3.js.map → unified-registry-L5PGLSEI.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  computeCostUSD
3
- } from "./chunk-COJOUIO2.js";
3
+ } from "./chunk-VN3CKPEF.js";
4
4
  import {
5
5
  DEFAULT_CONSENSUS_CONFIG,
6
6
  DEFAULT_INCREMENTAL_QUORUM_CONFIG,
@@ -18,20 +18,20 @@ import {
18
18
  toolSuccess,
19
19
  withProgressHeartbeat,
20
20
  wrapToolWithTimeout
21
- } from "./chunk-6UCWR3DS.js";
21
+ } from "./chunk-JVZ7FGWR.js";
22
22
  import {
23
23
  getToolMemory
24
- } from "./chunk-33MFMXBQ.js";
24
+ } from "./chunk-ESP6U3LW.js";
25
25
  import {
26
26
  createEvent,
27
27
  getGlobalRegistry
28
- } from "./chunk-WYJJUF6N.js";
28
+ } from "./chunk-HMZT2SJK.js";
29
29
  import {
30
30
  authRemediation,
31
31
  delay,
32
32
  getAvailableClis,
33
33
  withTimeout
34
- } from "./chunk-3EYXPV5F.js";
34
+ } from "./chunk-GWOXPCIF.js";
35
35
  import {
36
36
  AgentError,
37
37
  CLI_NAMES,
@@ -58,14 +58,16 @@ import {
58
58
  registerPersistentOutcomeStoreFactory,
59
59
  resolveClassGuardMs,
60
60
  resolveVoteTimeout
61
- } from "./chunk-DBDWMHUL.js";
61
+ } from "./chunk-OCJEYHUQ.js";
62
62
  import {
63
63
  ensureLearningDir,
64
- findRepoRoot,
65
- getOutcomesFile,
64
+ getOutcomesFile
65
+ } from "./chunk-5SXGPX34.js";
66
+ import {
67
+ getNexusDataDir,
66
68
  nexusDataPath,
67
69
  nexusDataPathEnsure
68
- } from "./chunk-GZ4NF4ZW.js";
70
+ } from "./chunk-L4QFWOOQ.js";
69
71
 
70
72
  // src/mcp/tools/consensus-vote.ts
71
73
  import { z as z10 } from "zod";
@@ -4205,7 +4207,7 @@ function panelDegradationWarning(errorCount, total) {
4205
4207
  if (errorCount <= 0 || errorCount >= total) return void 0;
4206
4208
  return `Panel degraded: ${String(errorCount)} of ${String(total)} voters errored; decision rests on ${String(total - errorCount)} voter(s).`;
4207
4209
  }
4208
- function buildResponse(input, result, costSummary) {
4210
+ function buildResponse(input, result, costSummary, voteRecord) {
4209
4211
  const proposalTruncated = input.proposal.length > 200 ? input.proposal.slice(0, 200) + "..." : input.proposal;
4210
4212
  const errorCount = result.votes.filter((v) => v.source === "error").length;
4211
4213
  const allErrors = errorCount === result.votes.length && errorCount > 0;
@@ -4223,8 +4225,14 @@ function buildResponse(input, result, costSummary) {
4223
4225
  },
4224
4226
  votes: result.votes.map(toAgentVoteSummary),
4225
4227
  durationMs: result.totalTimeMs,
4226
- simulateVotes: result.simulateVotes
4228
+ simulateVotes: result.simulateVotes,
4229
+ // #3991: surface the authentic-vote-record persistence outcome so a skipped
4230
+ // or failed persist is visible to the MCP caller (was WARN-only).
4231
+ voteRecordPersisted: voteRecord?.persisted ?? false
4227
4232
  };
4233
+ if (voteRecord !== void 0 && !voteRecord.persisted) {
4234
+ response.voteRecordNote = voteRecord.detail;
4235
+ }
4228
4236
  applyOptionalResponseFields(response, input, result, errorCount, costSummary);
4229
4237
  return response;
4230
4238
  }
@@ -4298,7 +4306,7 @@ function applyErrorPolicy(votes, policy) {
4298
4306
 
4299
4307
  // src/audit/vote-record-store.ts
4300
4308
  import { appendFileSync as appendFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2 } from "fs";
4301
- import { dirname, isAbsolute, join, resolve } from "path";
4309
+ import { dirname, isAbsolute, relative, resolve, sep } from "path";
4302
4310
 
4303
4311
  // src/audit/vote-record.ts
4304
4312
  import * as crypto from "crypto";
@@ -4399,9 +4407,13 @@ function hashProposal(proposal) {
4399
4407
  }
4400
4408
 
4401
4409
  // src/audit/vote-record-store.ts
4402
- var VOTE_RECORDS_REL_PATH = "governance/vote-records.jsonl";
4410
+ var VOTE_RECORDS_DATA_CATEGORY = "governance";
4411
+ var VOTE_RECORDS_FILENAME = "vote-records.jsonl";
4403
4412
  var VOTE_RECORDS_PATH_ENV = "NEXUS_VOTE_RECORDS_PATH";
4404
4413
  var MAX_PROPOSAL_RECORD_CHARS = 500;
4414
+ function voteRecordWriteFailedMessage(path) {
4415
+ return `Authentic vote record NOT persisted: the resolved data directory is not writable (${path}). Check filesystem permissions on the .nexus-agents data dir, or set ${VOTE_RECORDS_PATH_ENV} to a writable absolute file path. See server logs for the underlying filesystem error.`;
4416
+ }
4405
4417
  function outcomeToDecision(result) {
4406
4418
  if (result.outcome === "approved") return "approved";
4407
4419
  if (!result.quorumReached && result.outcome !== "rejected") return "no_quorum";
@@ -4456,23 +4468,36 @@ function readLedgerTip(filePath, logger10) {
4456
4468
  return { maxSequence: -1, lastHash: void 0 };
4457
4469
  }
4458
4470
  }
4471
+ function isWithin(root, target) {
4472
+ const resolvedRoot = resolve(root);
4473
+ const resolvedTarget = resolve(target);
4474
+ if (resolvedTarget === resolvedRoot) return true;
4475
+ const rel = relative(resolvedRoot, resolvedTarget);
4476
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute(rel);
4477
+ }
4459
4478
  function resolveVoteRecordsPath() {
4460
4479
  const envPath = process.env[VOTE_RECORDS_PATH_ENV];
4461
4480
  if (envPath !== void 0 && envPath.trim() !== "") {
4462
- return isAbsolute(envPath) ? envPath : resolve(envPath);
4481
+ const resolved2 = isAbsolute(envPath) ? envPath : resolve(envPath);
4482
+ if (!isAbsolute(envPath) && !isWithin(process.cwd(), resolved2)) {
4483
+ return void 0;
4484
+ }
4485
+ return resolved2;
4463
4486
  }
4464
- const root = findRepoRoot(process.cwd());
4465
- if (root === null) return void 0;
4466
- return join(root, VOTE_RECORDS_REL_PATH);
4487
+ const resolved = nexusDataPath(VOTE_RECORDS_DATA_CATEGORY, VOTE_RECORDS_FILENAME);
4488
+ const expectedSuffix = `${VOTE_RECORDS_DATA_CATEGORY}${sep}${VOTE_RECORDS_FILENAME}`;
4489
+ const underHomedirRoot = isWithin(getNexusDataDir(), resolved);
4490
+ const underRepoDataDir = resolved.includes(`.nexus-agents${sep}${VOTE_RECORDS_DATA_CATEGORY}${sep}`);
4491
+ if (!isAbsolute(resolved) || !resolved.endsWith(expectedSuffix) || !(underHomedirRoot || underRepoDataDir)) {
4492
+ return void 0;
4493
+ }
4494
+ return resolved;
4467
4495
  }
4468
4496
  function persistVoteRecord(opts) {
4469
4497
  const logger10 = opts.logger ?? createLogger({ component: "vote-record-store" });
4470
4498
  const filePath = opts.filePath ?? resolveVoteRecordsPath();
4471
4499
  if (filePath === void 0) {
4472
- logger10.warn(
4473
- `Authentic vote record NOT persisted: no repo root found from process.cwd() and no override set. Per #3927 the authoritative population path is caller-commits \u2014 commit the returned record bytes into ${VOTE_RECORDS_REL_PATH} in the promotion PR. To force a server-side write, set ${VOTE_RECORDS_PATH_ENV} to an absolute file path.`,
4474
- { id: opts.id }
4475
- );
4500
+ logger10.warn(voteRecordWriteFailedMessage("<unresolved>"), { id: opts.id });
4476
4501
  return void 0;
4477
4502
  }
4478
4503
  try {
@@ -4684,10 +4709,20 @@ function recordAuthenticVote(args) {
4684
4709
  const allSimulated = args.votes.length > 0 && args.votes.every((v) => v.source === "simulation");
4685
4710
  if (allSimulated) {
4686
4711
  logger6.debug("Skipping authentic vote record \u2014 all votes simulated");
4687
- return void 0;
4712
+ return {
4713
+ persisted: false,
4714
+ reason: "all-simulated",
4715
+ detail: "All votes were simulated; a committed vote record would seed governance from random output (#2319), so persistence is skipped by design."
4716
+ };
4717
+ }
4718
+ const resolvedPath = resolveVoteRecordsPath();
4719
+ if (resolvedPath === void 0) {
4720
+ const detail = voteRecordWriteFailedMessage("<unresolved>");
4721
+ logger6.warn(detail);
4722
+ return { persisted: false, reason: "write-failed", detail };
4688
4723
  }
4689
4724
  const id = `vote-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;
4690
- return persistVoteRecord({
4725
+ const record = persistVoteRecord({
4691
4726
  id,
4692
4727
  proposal: args.proposal,
4693
4728
  strategy: toRecordStrategy(args.strategy),
@@ -4696,6 +4731,14 @@ function recordAuthenticVote(args) {
4696
4731
  ...args.correlationId !== void 0 ? { correlationId: args.correlationId } : {},
4697
4732
  logger: logger6
4698
4733
  });
4734
+ if (record === void 0) {
4735
+ return {
4736
+ persisted: false,
4737
+ reason: "write-failed",
4738
+ detail: voteRecordWriteFailedMessage(resolvedPath)
4739
+ };
4740
+ }
4741
+ return { persisted: true, record };
4699
4742
  }
4700
4743
  function recordVoteError(proposal, errorMessage) {
4701
4744
  try {
@@ -5501,7 +5544,7 @@ async function processVotesWithCascade(engineVotes, opts) {
5501
5544
  var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
5502
5545
  async function runContrarianCheck(proposal, log) {
5503
5546
  try {
5504
- const { executeExpert } = await import("./expert-bridge-GMB5IHHF.js");
5547
+ const { executeExpert } = await import("./expert-bridge-NY6FAFQH.js");
5505
5548
  const prompt = [
5506
5549
  "You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
5507
5550
  "Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
@@ -5659,21 +5702,23 @@ function finalizeVotingResult(args) {
5659
5702
  }
5660
5703
  function recordVoteSideEffects(proposal, strategy, result, logger10) {
5661
5704
  const decisionId = `consensus-${String(getTimeProvider().now())}-${randomUUID2().slice(0, 8)}`;
5662
- recordAuthenticVote({
5705
+ const voteRecord = recordAuthenticVote({
5663
5706
  proposal,
5664
5707
  strategy,
5665
5708
  result: result.result,
5666
5709
  votes: result.votes,
5667
5710
  correlationId: decisionId
5668
5711
  });
5712
+ let costSummary;
5669
5713
  try {
5670
- return recordDecisionCost({ decisionId, gate: "consensus_vote", votes: result.votes });
5714
+ costSummary = recordDecisionCost({ decisionId, gate: "consensus_vote", votes: result.votes });
5671
5715
  } catch (costError) {
5672
5716
  logger10.warn("Per-decision cost rollup failed (non-fatal)", {
5673
5717
  error: getErrorMessage(costError)
5674
5718
  });
5675
- return void 0;
5719
+ costSummary = void 0;
5676
5720
  }
5721
+ return { costSummary, voteRecord };
5677
5722
  }
5678
5723
  async function handleConsensusVote(deps, args) {
5679
5724
  const logger10 = deps.logger ?? createLogger({ tool: "consensus_vote" });
@@ -5698,9 +5743,14 @@ async function handleConsensusVote(deps, args) {
5698
5743
  result.totalTimeMs,
5699
5744
  result.votes
5700
5745
  );
5701
- const costSummary = recordVoteSideEffects(args.proposal, strategy, result, logger10);
5746
+ const { costSummary, voteRecord } = recordVoteSideEffects(
5747
+ args.proposal,
5748
+ strategy,
5749
+ result,
5750
+ logger10
5751
+ );
5702
5752
  emitVoteRejectedSignal(result.result, getPipelineEventBus(), logger10);
5703
- return { ok: true, value: buildResponse(args, result, costSummary) };
5753
+ return { ok: true, value: buildResponse(args, result, costSummary, voteRecord) };
5704
5754
  } catch (error) {
5705
5755
  const message = getErrorMessage(error);
5706
5756
  const cause = error instanceof Error ? error : new Error(message);
@@ -5828,7 +5878,14 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
5828
5878
  }).optional(),
5829
5879
  // #3124: explains a `rejected` decision that coexists with a high
5830
5880
  // approvalPercentage (an error-policy short-circuit, e.g. fail_closed).
5831
- policyReason: z10.string().max(200).optional()
5881
+ policyReason: z10.string().max(200).optional(),
5882
+ // #3991: whether the authentic vote record was persisted at vote time. Post-
5883
+ // #3991 it routes through nexusDataPath under governance/, so true is the
5884
+ // normal case; false means all-simulated (skipped by design) or write-failed
5885
+ // (data dir unwritable) — voteRecordNote carries the actionable reason. Makes
5886
+ // a previously WARN-only skip visible to MCP callers.
5887
+ voteRecordPersisted: z10.boolean(),
5888
+ voteRecordNote: z10.string().max(500).optional()
5832
5889
  };
5833
5890
  function registerConsensusVoteTool(server, deps) {
5834
5891
  const logger10 = deps.logger ?? createLogger({ tool: "consensus_vote" });
@@ -5843,7 +5900,7 @@ function registerConsensusVoteTool(server, deps) {
5843
5900
  quickMode: z10.boolean().optional().default(false).describe("Use 3 agents instead of 7"),
5844
5901
  simulateVotes: z10.boolean().optional().default(false).describe("TESTS ONLY \u2014 random output, must not be used for real decisions (#2319)")
5845
5902
  };
5846
- const description = "Execute multi-model consensus voting on a proposal. Uses 7 specialized agent roles (architect, security, devex, ai_ml, pm, catfish, scope_steward) to vote on proposals with configurable strategies. Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514).";
5903
+ const 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. Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514). Supports async mode (mode: 'async') \u2014 returns a jobId to poll via get_job_result.";
5847
5904
  const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {
5848
5905
  toolName: "consensus_vote",
5849
5906
  rateLimiter: deps.rateLimiter,
@@ -5941,4 +5998,4 @@ export {
5941
5998
  CONSENSUS_VOTE_OUTPUT_SCHEMA,
5942
5999
  registerConsensusVoteTool
5943
6000
  };
5944
- //# sourceMappingURL=chunk-DLUFDKPA.js.map
6001
+ //# sourceMappingURL=chunk-N67LHY47.js.map