nexus-agents 2.133.0 → 2.134.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 (131) hide show
  1. package/dist/{child-mcp-config-R67B2KM6.js → child-mcp-config-TWHH63UK.js} +3 -3
  2. package/dist/{chunk-GYDO2WOR.js → chunk-33MFMXBQ.js} +5 -5
  3. package/dist/{chunk-VZCQRLXT.js → chunk-3EYXPV5F.js} +7 -7
  4. package/dist/{chunk-RLYXX3FQ.js → chunk-6LMZ7HFU.js} +2 -2
  5. package/dist/{chunk-4CLBJ2NA.js → chunk-6UCWR3DS.js} +3 -3
  6. package/dist/{chunk-RJEP2AZW.js → chunk-76R5ES6Z.js} +36 -36
  7. package/dist/{chunk-RJEP2AZW.js.map → chunk-76R5ES6Z.js.map} +1 -1
  8. package/dist/{chunk-HGUO36KW.js → chunk-7GSYICTL.js} +8 -8
  9. package/dist/{chunk-ZVBGZBW5.js → chunk-7TQZR5VU.js} +114 -7
  10. package/dist/chunk-7TQZR5VU.js.map +1 -0
  11. package/dist/{chunk-2CLFX73Y.js → chunk-B26FGLIJ.js} +2 -2
  12. package/dist/{chunk-27DRQWON.js → chunk-BTYYZ6VU.js} +4 -4
  13. package/dist/{chunk-K5WBFAR4.js → chunk-CLRSNWRQ.js} +4 -4
  14. package/dist/{chunk-TGGR6ST5.js → chunk-COJOUIO2.js} +3 -3
  15. package/dist/{chunk-QJIHSQZX.js → chunk-DBDWMHUL.js} +65 -14
  16. package/dist/chunk-DBDWMHUL.js.map +1 -0
  17. package/dist/{chunk-4CVITS5D.js → chunk-DLUFDKPA.js} +9 -9
  18. package/dist/{chunk-PM63X3QG.js → chunk-E64SZTEP.js} +3 -3
  19. package/dist/{chunk-QMCHVYZB.js → chunk-EHLJLIHS.js} +2 -2
  20. package/dist/{chunk-ZTRBMKXK.js → chunk-F74ZGHAP.js} +2 -2
  21. package/dist/{chunk-NZGNOXXW.js → chunk-FPMQ2JAK.js} +2 -2
  22. package/dist/{chunk-4DLHM6LI.js → chunk-FSFF7EFR.js} +2 -2
  23. package/dist/{chunk-J435FU54.js → chunk-FUJ3XR7T.js} +4 -4
  24. package/dist/{chunk-CI5KGCX5.js → chunk-FVSZLVMR.js} +3 -3
  25. package/dist/{chunk-RUSP5PJR.js → chunk-GZ4NF4ZW.js} +5 -1
  26. package/dist/{chunk-RUSP5PJR.js.map → chunk-GZ4NF4ZW.js.map} +1 -1
  27. package/dist/{chunk-DETYVPZO.js → chunk-IWQH6TP7.js} +6 -6
  28. package/dist/{chunk-ZQEQVCIU.js → chunk-MY52DFXC.js} +2 -2
  29. package/dist/{chunk-FKTLAPXJ.js → chunk-OCKZ6F5O.js} +3 -3
  30. package/dist/{chunk-E4IYX7LD.js → chunk-ORQAFTAZ.js} +2 -2
  31. package/dist/{chunk-QLRH6KOT.js → chunk-OU2NQVKD.js} +2 -2
  32. package/dist/{chunk-7BONPRR2.js → chunk-PFBV5FCT.js} +2 -2
  33. package/dist/{chunk-S4U3Z6ZS.js → chunk-QZUT22LP.js} +6 -6
  34. package/dist/{chunk-EFDXX5MC.js → chunk-UDB5NHJI.js} +3 -3
  35. package/dist/{chunk-RAWF4JOT.js → chunk-VI7LELES.js} +7 -7
  36. package/dist/{chunk-ECDJM6UB.js → chunk-WFKVUZ3O.js} +2 -2
  37. package/dist/{chunk-XIFOAZ5B.js → chunk-WYJJUF6N.js} +4 -4
  38. package/dist/{chunk-GET2MTLW.js → chunk-Z6DXZ6AS.js} +2 -2
  39. package/dist/{chunk-WHZD2W6Q.js → chunk-ZMDOGN33.js} +2 -2
  40. package/dist/{cli-circuit-breaker-J6UFONNE.js → cli-circuit-breaker-VXBDCAD7.js} +5 -5
  41. package/dist/cli.js +844 -155
  42. package/dist/cli.js.map +1 -1
  43. package/dist/{composite-router-HQUSCJO4.js → composite-router-E6FXXMMR.js} +3 -3
  44. package/dist/{consensus-vote-MVZ27Y43.js → consensus-vote-R6X5IL57.js} +15 -15
  45. package/dist/{context-retriever-5OVRAWNZ.js → context-retriever-I4NEOUEV.js} +9 -9
  46. package/dist/{doctor-deep-HJ3NQ365.js → doctor-deep-CZXN4YD6.js} +4 -4
  47. package/dist/{expert-bridge-MINXBC73.js → expert-bridge-GMB5IHHF.js} +5 -5
  48. package/dist/factory-WR62MEIJ.js +14 -0
  49. package/dist/factory-ZBQGA373.js +21 -0
  50. package/dist/{improvement-review-ZL3364R2.js → improvement-review-77BKIQGN.js} +5 -5
  51. package/dist/index.d.ts +210 -192
  52. package/dist/index.js +30 -30
  53. package/dist/{init-opencode-L3NT524E.js → init-opencode-4H2VPN23.js} +7 -7
  54. package/dist/issue-triage-NJB6SL4S.js +16 -0
  55. package/dist/{learning-persistence-QFCQ5POD.js → learning-persistence-2KO4CXNL.js} +2 -2
  56. package/dist/{pr-reviewer-helpers-PLKDVWYF.js → pr-reviewer-helpers-F3SHCHNV.js} +5 -5
  57. package/dist/{registry-command-HPKNLYUL.js → registry-command-VFCSMHME.js} +3 -3
  58. package/dist/{repo-security-plan-HSYGGVEJ.js → repo-security-plan-U2ZIFW53.js} +4 -4
  59. package/dist/research-helpers-synthesize-5TLNHT3I.js +14 -0
  60. package/dist/{routing-memory-OGUOL7UF.js → routing-memory-VVLJL3MG.js} +3 -3
  61. package/dist/{session-memory-HQWAXH3C.js → session-memory-GMQYZLJE.js} +4 -4
  62. package/dist/{setup-command-CIXJXFPC.js → setup-command-IMAX6EAO.js} +12 -12
  63. package/dist/setup-config-2ZSJ3HNE.js +10 -0
  64. package/dist/{setup-custom-api-W7EDVKWR.js → setup-custom-api-NJGCRIRO.js} +4 -4
  65. package/dist/{tool-memory-Z2B7CAH7.js → tool-memory-TSYJXGOV.js} +6 -6
  66. package/dist/unified-registry-IMAL3SY6.js +24 -0
  67. package/dist/{weather-report-GX7OIUL2.js → weather-report-OU65NJS3.js} +3 -3
  68. package/package.json +1 -1
  69. package/dist/chunk-QJIHSQZX.js.map +0 -1
  70. package/dist/chunk-ZVBGZBW5.js.map +0 -1
  71. package/dist/factory-KC7BYHAP.js +0 -21
  72. package/dist/factory-ZG2FZYVA.js +0 -14
  73. package/dist/issue-triage-CZPFNGB7.js +0 -16
  74. package/dist/research-helpers-synthesize-IQHDU27S.js +0 -14
  75. package/dist/setup-config-HYX3BRSE.js +0 -10
  76. package/dist/unified-registry-UFNSWKZA.js +0 -24
  77. /package/dist/{child-mcp-config-R67B2KM6.js.map → child-mcp-config-TWHH63UK.js.map} +0 -0
  78. /package/dist/{chunk-GYDO2WOR.js.map → chunk-33MFMXBQ.js.map} +0 -0
  79. /package/dist/{chunk-VZCQRLXT.js.map → chunk-3EYXPV5F.js.map} +0 -0
  80. /package/dist/{chunk-RLYXX3FQ.js.map → chunk-6LMZ7HFU.js.map} +0 -0
  81. /package/dist/{chunk-4CLBJ2NA.js.map → chunk-6UCWR3DS.js.map} +0 -0
  82. /package/dist/{chunk-HGUO36KW.js.map → chunk-7GSYICTL.js.map} +0 -0
  83. /package/dist/{chunk-2CLFX73Y.js.map → chunk-B26FGLIJ.js.map} +0 -0
  84. /package/dist/{chunk-27DRQWON.js.map → chunk-BTYYZ6VU.js.map} +0 -0
  85. /package/dist/{chunk-K5WBFAR4.js.map → chunk-CLRSNWRQ.js.map} +0 -0
  86. /package/dist/{chunk-TGGR6ST5.js.map → chunk-COJOUIO2.js.map} +0 -0
  87. /package/dist/{chunk-4CVITS5D.js.map → chunk-DLUFDKPA.js.map} +0 -0
  88. /package/dist/{chunk-PM63X3QG.js.map → chunk-E64SZTEP.js.map} +0 -0
  89. /package/dist/{chunk-QMCHVYZB.js.map → chunk-EHLJLIHS.js.map} +0 -0
  90. /package/dist/{chunk-ZTRBMKXK.js.map → chunk-F74ZGHAP.js.map} +0 -0
  91. /package/dist/{chunk-NZGNOXXW.js.map → chunk-FPMQ2JAK.js.map} +0 -0
  92. /package/dist/{chunk-4DLHM6LI.js.map → chunk-FSFF7EFR.js.map} +0 -0
  93. /package/dist/{chunk-J435FU54.js.map → chunk-FUJ3XR7T.js.map} +0 -0
  94. /package/dist/{chunk-CI5KGCX5.js.map → chunk-FVSZLVMR.js.map} +0 -0
  95. /package/dist/{chunk-DETYVPZO.js.map → chunk-IWQH6TP7.js.map} +0 -0
  96. /package/dist/{chunk-ZQEQVCIU.js.map → chunk-MY52DFXC.js.map} +0 -0
  97. /package/dist/{chunk-FKTLAPXJ.js.map → chunk-OCKZ6F5O.js.map} +0 -0
  98. /package/dist/{chunk-E4IYX7LD.js.map → chunk-ORQAFTAZ.js.map} +0 -0
  99. /package/dist/{chunk-QLRH6KOT.js.map → chunk-OU2NQVKD.js.map} +0 -0
  100. /package/dist/{chunk-7BONPRR2.js.map → chunk-PFBV5FCT.js.map} +0 -0
  101. /package/dist/{chunk-S4U3Z6ZS.js.map → chunk-QZUT22LP.js.map} +0 -0
  102. /package/dist/{chunk-EFDXX5MC.js.map → chunk-UDB5NHJI.js.map} +0 -0
  103. /package/dist/{chunk-RAWF4JOT.js.map → chunk-VI7LELES.js.map} +0 -0
  104. /package/dist/{chunk-ECDJM6UB.js.map → chunk-WFKVUZ3O.js.map} +0 -0
  105. /package/dist/{chunk-XIFOAZ5B.js.map → chunk-WYJJUF6N.js.map} +0 -0
  106. /package/dist/{chunk-GET2MTLW.js.map → chunk-Z6DXZ6AS.js.map} +0 -0
  107. /package/dist/{chunk-WHZD2W6Q.js.map → chunk-ZMDOGN33.js.map} +0 -0
  108. /package/dist/{cli-circuit-breaker-J6UFONNE.js.map → cli-circuit-breaker-VXBDCAD7.js.map} +0 -0
  109. /package/dist/{composite-router-HQUSCJO4.js.map → composite-router-E6FXXMMR.js.map} +0 -0
  110. /package/dist/{consensus-vote-MVZ27Y43.js.map → consensus-vote-R6X5IL57.js.map} +0 -0
  111. /package/dist/{context-retriever-5OVRAWNZ.js.map → context-retriever-I4NEOUEV.js.map} +0 -0
  112. /package/dist/{doctor-deep-HJ3NQ365.js.map → doctor-deep-CZXN4YD6.js.map} +0 -0
  113. /package/dist/{expert-bridge-MINXBC73.js.map → expert-bridge-GMB5IHHF.js.map} +0 -0
  114. /package/dist/{factory-KC7BYHAP.js.map → factory-WR62MEIJ.js.map} +0 -0
  115. /package/dist/{factory-ZG2FZYVA.js.map → factory-ZBQGA373.js.map} +0 -0
  116. /package/dist/{improvement-review-ZL3364R2.js.map → improvement-review-77BKIQGN.js.map} +0 -0
  117. /package/dist/{init-opencode-L3NT524E.js.map → init-opencode-4H2VPN23.js.map} +0 -0
  118. /package/dist/{issue-triage-CZPFNGB7.js.map → issue-triage-NJB6SL4S.js.map} +0 -0
  119. /package/dist/{learning-persistence-QFCQ5POD.js.map → learning-persistence-2KO4CXNL.js.map} +0 -0
  120. /package/dist/{pr-reviewer-helpers-PLKDVWYF.js.map → pr-reviewer-helpers-F3SHCHNV.js.map} +0 -0
  121. /package/dist/{registry-command-HPKNLYUL.js.map → registry-command-VFCSMHME.js.map} +0 -0
  122. /package/dist/{repo-security-plan-HSYGGVEJ.js.map → repo-security-plan-U2ZIFW53.js.map} +0 -0
  123. /package/dist/{research-helpers-synthesize-IQHDU27S.js.map → research-helpers-synthesize-5TLNHT3I.js.map} +0 -0
  124. /package/dist/{routing-memory-OGUOL7UF.js.map → routing-memory-VVLJL3MG.js.map} +0 -0
  125. /package/dist/{session-memory-HQWAXH3C.js.map → session-memory-GMQYZLJE.js.map} +0 -0
  126. /package/dist/{setup-command-CIXJXFPC.js.map → setup-command-IMAX6EAO.js.map} +0 -0
  127. /package/dist/{setup-config-HYX3BRSE.js.map → setup-config-2ZSJ3HNE.js.map} +0 -0
  128. /package/dist/{setup-custom-api-W7EDVKWR.js.map → setup-custom-api-NJGCRIRO.js.map} +0 -0
  129. /package/dist/{tool-memory-Z2B7CAH7.js.map → tool-memory-TSYJXGOV.js.map} +0 -0
  130. /package/dist/{unified-registry-UFNSWKZA.js.map → unified-registry-IMAL3SY6.js.map} +0 -0
  131. /package/dist/{weather-report-GX7OIUL2.js.map → weather-report-OU65NJS3.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -13,17 +13,17 @@ import {
13
13
  generateSummary,
14
14
  parseFindings,
15
15
  sumFindings
16
- } from "./chunk-FKTLAPXJ.js";
17
- import "./chunk-RLYXX3FQ.js";
16
+ } from "./chunk-OCKZ6F5O.js";
17
+ import "./chunk-6LMZ7HFU.js";
18
18
  import {
19
19
  buildOpenAICompatAdapters,
20
20
  readOpenAICompatEnv
21
- } from "./chunk-27DRQWON.js";
21
+ } from "./chunk-BTYYZ6VU.js";
22
22
  import {
23
23
  setupCommandAsync,
24
24
  verifyCommand
25
- } from "./chunk-DETYVPZO.js";
26
- import "./chunk-QLRH6KOT.js";
25
+ } from "./chunk-IWQH6TP7.js";
26
+ import "./chunk-OU2NQVKD.js";
27
27
  import {
28
28
  AuthHandler,
29
29
  DEFAULT_EXPERTS,
@@ -142,18 +142,18 @@ import {
142
142
  validateCommand,
143
143
  validateWorkflow,
144
144
  wrapInMarkdownFence
145
- } from "./chunk-RJEP2AZW.js";
146
- import "./chunk-GET2MTLW.js";
145
+ } from "./chunk-76R5ES6Z.js";
146
+ import "./chunk-Z6DXZ6AS.js";
147
147
  import "./chunk-3ACDP4E6.js";
148
148
  import {
149
149
  CATEGORY_DISPLAY_NAMES,
150
150
  DEFAULT_PR_REVIEW_CONFIG
151
151
  } from "./chunk-WAYGXUSM.js";
152
- import "./chunk-PM63X3QG.js";
153
- import "./chunk-CI5KGCX5.js";
152
+ import "./chunk-E64SZTEP.js";
153
+ import "./chunk-FVSZLVMR.js";
154
154
  import {
155
155
  shutdownExpertBridge
156
- } from "./chunk-RAWF4JOT.js";
156
+ } from "./chunk-VI7LELES.js";
157
157
  import {
158
158
  ConsensusVoteInputSchema,
159
159
  DEFAULT_VOTE_TIMEOUT_MS,
@@ -162,25 +162,25 @@ import {
162
162
  VoteThresholdSchema,
163
163
  executeVoting,
164
164
  registerConsensusVoteTool
165
- } from "./chunk-4CVITS5D.js";
165
+ } from "./chunk-DLUFDKPA.js";
166
166
  import {
167
167
  loadUsageEvents,
168
168
  rollupByModel
169
- } from "./chunk-TGGR6ST5.js";
169
+ } from "./chunk-COJOUIO2.js";
170
170
  import {
171
171
  synthesizeResearch
172
- } from "./chunk-EFDXX5MC.js";
172
+ } from "./chunk-UDB5NHJI.js";
173
173
  import {
174
174
  classifyTrust,
175
175
  createFullGitHubProvider,
176
176
  evaluatePolicy,
177
177
  parsePRUrl
178
- } from "./chunk-J435FU54.js";
179
- import "./chunk-4DLHM6LI.js";
178
+ } from "./chunk-FUJ3XR7T.js";
179
+ import "./chunk-FSFF7EFR.js";
180
180
  import {
181
181
  ReputationCache,
182
182
  sanitizeInput
183
- } from "./chunk-QMCHVYZB.js";
183
+ } from "./chunk-EHLJLIHS.js";
184
184
  import {
185
185
  ImprovementReviewInputSchema,
186
186
  calculateFitnessScore,
@@ -194,10 +194,10 @@ import {
194
194
  registerImprovementReviewTool,
195
195
  runImprovementReview,
196
196
  scanForSecrets
197
- } from "./chunk-ZVBGZBW5.js";
197
+ } from "./chunk-7TQZR5VU.js";
198
198
  import {
199
199
  createDefaultPolicyFirewall
200
- } from "./chunk-4CLBJ2NA.js";
200
+ } from "./chunk-6UCWR3DS.js";
201
201
  import "./chunk-HFOQKCD2.js";
202
202
  import {
203
203
  PaperStatusSchema,
@@ -221,20 +221,20 @@ import {
221
221
  loadSourcesRegistry,
222
222
  rankDiscoveredItems,
223
223
  saveSourcesRegistry
224
- } from "./chunk-S4U3Z6ZS.js";
224
+ } from "./chunk-QZUT22LP.js";
225
225
  import {
226
226
  resolveToken
227
- } from "./chunk-ZQEQVCIU.js";
227
+ } from "./chunk-MY52DFXC.js";
228
228
  import {
229
229
  loadPapersRegistry,
230
230
  loadTechniquesRegistry,
231
231
  savePapersRegistry
232
- } from "./chunk-2CLFX73Y.js";
232
+ } from "./chunk-B26FGLIJ.js";
233
233
  import {
234
234
  MemoryError,
235
235
  shutdownToolMemory
236
- } from "./chunk-GYDO2WOR.js";
237
- import "./chunk-NZGNOXXW.js";
236
+ } from "./chunk-33MFMXBQ.js";
237
+ import "./chunk-FPMQ2JAK.js";
238
238
  import {
239
239
  CustomExpertDefinitionSchema,
240
240
  DATA_SUBDIRECTORIES,
@@ -254,7 +254,7 @@ import {
254
254
  loadConfig,
255
255
  runDoctor,
256
256
  validateNexusEnv
257
- } from "./chunk-HGUO36KW.js";
257
+ } from "./chunk-7GSYICTL.js";
258
258
  import "./chunk-NUBSJGQZ.js";
259
259
  import {
260
260
  capitalize,
@@ -265,20 +265,20 @@ import "./chunk-ZM4O442V.js";
265
265
  import "./chunk-PQHVC4BD.js";
266
266
  import {
267
267
  createUnifiedRegistry
268
- } from "./chunk-XIFOAZ5B.js";
268
+ } from "./chunk-WYJJUF6N.js";
269
269
  import {
270
270
  createAllAdapters,
271
271
  getAvailableClis,
272
272
  isRecord,
273
273
  probeAllClis
274
- } from "./chunk-VZCQRLXT.js";
274
+ } from "./chunk-3EYXPV5F.js";
275
275
  import {
276
276
  DEFAULTS
277
- } from "./chunk-WHZD2W6Q.js";
278
- import "./chunk-ECDJM6UB.js";
279
- import "./chunk-ZTRBMKXK.js";
280
- import "./chunk-7BONPRR2.js";
281
- import "./chunk-E4IYX7LD.js";
277
+ } from "./chunk-ZMDOGN33.js";
278
+ import "./chunk-WFKVUZ3O.js";
279
+ import "./chunk-F74ZGHAP.js";
280
+ import "./chunk-PFBV5FCT.js";
281
+ import "./chunk-ORQAFTAZ.js";
282
282
  import {
283
283
  API_TIMEOUTS,
284
284
  AgentCapability,
@@ -352,16 +352,16 @@ import {
352
352
  validateTimeout,
353
353
  writeEmptyLine,
354
354
  writeLine
355
- } from "./chunk-QJIHSQZX.js";
355
+ } from "./chunk-DBDWMHUL.js";
356
356
  import {
357
357
  applyPortableMode,
358
358
  detectSandbox,
359
359
  findRepoRoot,
360
- getNexusDataDir,
361
360
  getPerRepoSubdirs,
362
361
  nexusDataPath,
362
+ nexusSharedPath,
363
363
  sessionsDbPath
364
- } from "./chunk-RUSP5PJR.js";
364
+ } from "./chunk-GZ4NF4ZW.js";
365
365
  import "./chunk-ZPWHCABL.js";
366
366
 
367
367
  // src/cli/cli-log-bootstrap.ts
@@ -1629,14 +1629,14 @@ ${colors.dim}Session ended.${colors.reset}
1629
1629
  });
1630
1630
  });
1631
1631
  rl.prompt();
1632
- return new Promise((resolve13) => {
1632
+ return new Promise((resolve14) => {
1633
1633
  rl.on("line", (line) => {
1634
1634
  void (async () => {
1635
1635
  try {
1636
1636
  const shouldExit = await processLine(line, session, logger19);
1637
1637
  if (shouldExit) {
1638
1638
  rl.close();
1639
- resolve13();
1639
+ resolve14();
1640
1640
  return;
1641
1641
  }
1642
1642
  } catch (error) {
@@ -1648,7 +1648,7 @@ ${colors.dim}Session ended.${colors.reset}
1648
1648
  })();
1649
1649
  });
1650
1650
  rl.on("close", () => {
1651
- resolve13();
1651
+ resolve14();
1652
1652
  });
1653
1653
  });
1654
1654
  }
@@ -2984,7 +2984,10 @@ var COMMAND_CATALOG = [
2984
2984
  },
2985
2985
  {
2986
2986
  command: "vote",
2987
- description: "Run consensus vote on a proposal (5-6 agents)",
2987
+ // Default panel is 7 roles; `--quick` runs 3 (getVoterRoles in
2988
+ // mcp/tools/consensus-vote.ts). Prior drift: "5-6 agents" here, "6 agents"
2989
+ // in HELP_TEXT, "6 agents by default" in COMMAND_HELP — all wrong (#3209).
2990
+ description: "Run consensus vote on a proposal (7 agents; --quick uses 3)",
2988
2991
  audience: "essential"
2989
2992
  },
2990
2993
  {
@@ -3227,6 +3230,9 @@ function filterCatalog(showAll) {
3227
3230
  function catalogForExtractors() {
3228
3231
  return COMMAND_CATALOG.filter((e) => e.command !== "(default)");
3229
3232
  }
3233
+ function getCommandDescription(command) {
3234
+ return COMMAND_CATALOG.find((e) => e.command === command)?.description;
3235
+ }
3230
3236
  function groupByAudience(entries) {
3231
3237
  const groups = /* @__PURE__ */ new Map();
3232
3238
  for (const entry of entries) {
@@ -3265,7 +3271,8 @@ function renderCommandsSection(showAll) {
3265
3271
  }
3266
3272
 
3267
3273
  // src/cli-help-text.ts
3268
- var HELP_TEXT = `
3274
+ var COMMANDS_PLACEHOLDER = "__COMMANDS__";
3275
+ var HELP_TEXT_FRAME = `
3269
3276
  nexus-agents - Intelligent orchestration platform for AI coding tools
3270
3277
 
3271
3278
  USAGE:
@@ -3273,44 +3280,7 @@ USAGE:
3273
3280
  nexus-agents [COMMAND] [SUBCOMMAND] [OPTIONS]
3274
3281
 
3275
3282
  COMMANDS:
3276
- (default) Start MCP server with stdio transport
3277
- hello Show welcome message and quick start (no API keys needed)
3278
- demo API-free exploration mode (no API keys needed)
3279
- setup Configure Claude CLI integration (MCP + CLAUDE.md rules)
3280
- login Show per-CLI auth status + login fix instructions
3281
- verify Quick installation verification (no API keys needed)
3282
- doctor Check CLI installations and health status
3283
- config Manage configuration (init, get, set, list, reset, export, import)
3284
- expert list List available experts (built-in and custom)
3285
- workflow list List available workflow templates
3286
- workflow run Execute a workflow template
3287
- review <url> Review a GitHub pull request (dogfooding)
3288
- routing-audit Debug model routing decisions
3289
- orchestrate Execute task using CLI tools (standalone mode)
3290
- vote Run consensus vote on a proposal (6 agents)
3291
- system-review Run automated system review (5-phase checklist)
3292
- sprint Automated sprint planning from open issues
3293
- session Manage session persistence (list, show, export, delete, prune)
3294
- evaluate Self-evaluation of codebase components
3295
- issue Issue template validation and management
3296
- index Generate and manage codebase index
3297
- research Manage research registry and index
3298
- validation Show learning validation dashboard
3299
- learning-metrics Show aggregated learning metrics dashboard
3300
- swe-bench Run SWE-bench evaluation benchmark
3301
- atbench Run ATBench trajectory-safety evaluation (#1981)
3302
- hooks Claude CLI hook integration commands
3303
- fitness-audit Run CLI orchestration fitness score audit
3304
- release-notes Generate release notes from git commits
3305
- release-validate Run expert swarm validation for releases
3306
- release-announce Generate release announcements (blog, Bluesky)
3307
- scaffold Generate project files from templates (tool, expert, workflow, command)
3308
- visualize Generate Mermaid diagrams and ASCII dashboards (architecture, swarm, flow)
3309
- capabilities Show model capabilities matrix (modalities, tools, features)
3310
- status At-a-glance project health dashboard (fitness, adapters, version)
3311
- health Swarm health metrics dashboard (utilization, routing accuracy, failures)
3312
- validate Run unified validation (doctor + fitness + config)
3313
- auth Manage MCP authentication tokens (init, show, rotate)
3283
+ ${COMMANDS_PLACEHOLDER}
3314
3284
 
3315
3285
  OPTIONS:
3316
3286
  -h, --help Show this help message
@@ -3336,14 +3306,13 @@ EXAMPLES:
3336
3306
 
3337
3307
  For more information, visit: https://github.com/nexus-substrate/nexus-agents
3338
3308
  `.trim();
3339
- var COMMANDS_BLOCK_RE = /COMMANDS:\n([\s\S]*?)\n\nOPTIONS:/;
3309
+ function composeHelp(commandsSection) {
3310
+ return HELP_TEXT_FRAME.replace(COMMANDS_PLACEHOLDER, commandsSection);
3311
+ }
3312
+ var HELP_TEXT = composeHelp(renderCommandsSection(true));
3340
3313
  function renderHelp(opts) {
3341
3314
  if (opts.all) return HELP_TEXT;
3342
- const replacement = renderCommandsSection(false);
3343
- return HELP_TEXT.replace(COMMANDS_BLOCK_RE, `COMMANDS:
3344
- ${replacement}
3345
-
3346
- OPTIONS:`);
3315
+ return composeHelp(renderCommandsSection(false));
3347
3316
  }
3348
3317
 
3349
3318
  // src/cli-types.ts
@@ -4055,7 +4024,7 @@ ${file.patch}
4055
4024
  violations: policyResult.violations
4056
4025
  });
4057
4026
  }
4058
- const { formatReviewComment: formatReviewComment2 } = await import("./pr-reviewer-helpers-PLKDVWYF.js");
4027
+ const { formatReviewComment: formatReviewComment2 } = await import("./pr-reviewer-helpers-F3SHCHNV.js");
4059
4028
  const body = formatReviewComment2(result);
4060
4029
  const postResult = await provider.createReview(pr.prNumber, body, result.decision);
4061
4030
  if (!postResult.ok) {
@@ -12987,7 +12956,7 @@ function writeResultAndExit(result) {
12987
12956
 
12988
12957
  // src/cli/hooks/hook-router.ts
12989
12958
  async function readStdin() {
12990
- return new Promise((resolve13, reject) => {
12959
+ return new Promise((resolve14, reject) => {
12991
12960
  let data = "";
12992
12961
  process.stdin.setEncoding("utf8");
12993
12962
  process.stdin.on("readable", () => {
@@ -12998,24 +12967,24 @@ async function readStdin() {
12998
12967
  }
12999
12968
  });
13000
12969
  process.stdin.on("end", () => {
13001
- resolve13(data);
12970
+ resolve14(data);
13002
12971
  });
13003
12972
  process.stdin.on("error", (err2) => {
13004
12973
  reject(err2);
13005
12974
  });
13006
12975
  if (process.stdin.isTTY) {
13007
- resolve13("");
12976
+ resolve14("");
13008
12977
  }
13009
12978
  });
13010
12979
  }
13011
12980
  async function readStdinWithTimeout(timeoutMs = 5e3) {
13012
- return new Promise((resolve13, reject) => {
12981
+ return new Promise((resolve14, reject) => {
13013
12982
  const timeout2 = setTimeout(() => {
13014
12983
  reject(new Error(`Stdin read timeout after ${String(timeoutMs)}ms`));
13015
12984
  }, timeoutMs);
13016
12985
  readStdin().then((data) => {
13017
12986
  clearTimeout(timeout2);
13018
- resolve13(data);
12987
+ resolve14(data);
13019
12988
  }).catch((err2) => {
13020
12989
  clearTimeout(timeout2);
13021
12990
  reject(err2 instanceof Error ? err2 : new Error(String(err2)));
@@ -14505,9 +14474,9 @@ function interactiveIO() {
14505
14474
  write: (text) => {
14506
14475
  process.stdout.write(text);
14507
14476
  },
14508
- prompt: (question) => new Promise((resolve13) => {
14477
+ prompt: (question) => new Promise((resolve14) => {
14509
14478
  rl.question(question, (answer) => {
14510
- resolve13(answer.trim());
14479
+ resolve14(answer.trim());
14511
14480
  });
14512
14481
  }),
14513
14482
  close: () => {
@@ -16956,9 +16925,6 @@ function authCommand(subcommand, options) {
16956
16925
  return result.success;
16957
16926
  }
16958
16927
 
16959
- // src/cli-commands-handlers.ts
16960
- import { existsSync as existsSync22 } from "fs";
16961
-
16962
16928
  // src/cli/init-portable.ts
16963
16929
  import {
16964
16930
  existsSync as existsSync21,
@@ -17042,8 +17008,8 @@ function autoGitignoreMcpConfig(workspaceDir, dryRun) {
17042
17008
  if (already) return false;
17043
17009
  }
17044
17010
  if (!dryRun) {
17045
- const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
17046
- appendFileSync(gitignorePath, `${sep3}${MCP_CONFIG_FILENAME}
17011
+ const sep4 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
17012
+ appendFileSync(gitignorePath, `${sep4}${MCP_CONFIG_FILENAME}
17047
17013
  `, "utf-8");
17048
17014
  }
17049
17015
  return true;
@@ -17282,8 +17248,8 @@ function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
17282
17248
  }
17283
17249
  }
17284
17250
  if (!dryRun) {
17285
- const sep3 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
17286
- appendFileSync2(gitignorePath, `${sep3}${entry}
17251
+ const sep4 = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
17252
+ appendFileSync2(gitignorePath, `${sep4}${entry}
17287
17253
  `, "utf-8");
17288
17254
  }
17289
17255
  return true;
@@ -17831,7 +17797,7 @@ function startImprovementReviewScheduler(options) {
17831
17797
  let running = false;
17832
17798
  const runOnce = async () => {
17833
17799
  try {
17834
- const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-ZL3364R2.js");
17800
+ const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-77BKIQGN.js");
17835
17801
  const input = ImprovementReviewInputSchema2.parse({ fileIssues });
17836
17802
  const result = await runImprovementReview2(input, { logger: logger19 });
17837
17803
  logger19.info("Scheduled improvement_review complete", {
@@ -18219,8 +18185,8 @@ async function initUpstreamServers(gatewayConfig, server, logger19) {
18219
18185
  servers: upstreamServers.length,
18220
18186
  tools: tools.length
18221
18187
  });
18222
- const { z: z11 } = await import("zod");
18223
- const passthroughSchema = z11.looseObject({});
18188
+ const { z: z14 } = await import("zod");
18189
+ const passthroughSchema = z14.looseObject({});
18224
18190
  for (const tool of tools) {
18225
18191
  const toolName = tool.name;
18226
18192
  const desc = tool.description ?? `Upstream tool: ${toolName}`;
@@ -18617,7 +18583,7 @@ async function executeReplTask(task, options, logger19, rl) {
18617
18583
  }
18618
18584
  }
18619
18585
  function runOrchestratorRepl(options, logger19) {
18620
- return new Promise((resolve13) => {
18586
+ return new Promise((resolve14) => {
18621
18587
  const rl = readline2.createInterface({
18622
18588
  input: process.stdin,
18623
18589
  output: process.stdout,
@@ -18640,7 +18606,7 @@ function runOrchestratorRepl(options, logger19) {
18640
18606
  });
18641
18607
  rl.on("close", () => {
18642
18608
  logger19.info("Orchestrator REPL closed");
18643
- resolve13();
18609
+ resolve14();
18644
18610
  });
18645
18611
  });
18646
18612
  }
@@ -19774,7 +19740,7 @@ function adaptConfigToLibrary(config) {
19774
19740
  }
19775
19741
  function createBeliefPromoter() {
19776
19742
  return async (event) => {
19777
- const { getToolMemory } = await import("./tool-memory-Z2B7CAH7.js");
19743
+ const { getToolMemory } = await import("./tool-memory-TSYJXGOV.js");
19778
19744
  const tm = getToolMemory();
19779
19745
  await tm.recordBelief(
19780
19746
  `skill:${event.name}`,
@@ -20517,18 +20483,7 @@ function buildOrchestratorOptions(args) {
20517
20483
  ...args.options.maxCostUsd !== void 0 && { maxCostUsd: args.options.maxCostUsd }
20518
20484
  };
20519
20485
  }
20520
- function printFirstRunHint() {
20521
- const isTTY = process.stderr.isTTY;
20522
- if (!isTTY) return;
20523
- const dataDir = getNexusDataDir();
20524
- const hasConfig = existsSync22("./.nexus-agents/nexus-agents.yaml") || existsSync22("./.nexus-agents/nexus-agents.yml") || existsSync22("./nexus-agents.yaml") || existsSync22("./nexus-agents.yml");
20525
- if (existsSync22(dataDir) || hasConfig) return;
20526
- process.stderr.write(
20527
- "\n\x1B[36mnexus-agents\x1B[0m: First time? Run \x1B[1mnexus-agents setup\x1B[0m to configure.\n\n"
20528
- );
20529
- }
20530
20486
  async function handleServerCommand(args) {
20531
- printFirstRunHint();
20532
20487
  if (args.options.interactive) {
20533
20488
  const exitCode = await replCommand({ verbose: args.options.verbose });
20534
20489
  return cliExitFromStatus(exitCode);
@@ -20638,7 +20593,7 @@ async function handleResearchCommand(args) {
20638
20593
  }
20639
20594
  }
20640
20595
  async function handleRegistryCommand(args) {
20641
- const { registryCommand, isValidRegistrySubcommand, formatRegistryUsage } = await import("./registry-command-HPKNLYUL.js");
20596
+ const { registryCommand, isValidRegistrySubcommand, formatRegistryUsage } = await import("./registry-command-VFCSMHME.js");
20642
20597
  const subcommand = args.subcommand;
20643
20598
  if (!isValidRegistrySubcommand(subcommand)) {
20644
20599
  process.stdout.write(`${formatRegistryUsage()}
@@ -20686,7 +20641,7 @@ async function handleVerifyCommand(args) {
20686
20641
  async function handleDoctorCommand(args) {
20687
20642
  const exitCode = await doctorCommand({ fix: args.options.fix });
20688
20643
  if (args.options.deep) {
20689
- const { runDeepDiagnostics: runDeepDiagnostics2, formatDeepDiagnostics: formatDeepDiagnostics2 } = await import("./doctor-deep-HJ3NQ365.js");
20644
+ const { runDeepDiagnostics: runDeepDiagnostics2, formatDeepDiagnostics: formatDeepDiagnostics2 } = await import("./doctor-deep-CZXN4YD6.js");
20690
20645
  const diag = runDeepDiagnostics2();
20691
20646
  process.stdout.write(formatDeepDiagnostics2(diag) + "\n");
20692
20647
  }
@@ -20736,7 +20691,7 @@ async function runInitPortableFlow(args) {
20736
20691
  return cliExit(result.success ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
20737
20692
  }
20738
20693
  async function runInitOpencodeFlow(args) {
20739
- const { runInitOpencode } = await import("./init-opencode-L3NT524E.js");
20694
+ const { runInitOpencode } = await import("./init-opencode-4H2VPN23.js");
20740
20695
  const opencodePath = args.options.opencode;
20741
20696
  if (opencodePath === void 0 || opencodePath === "") {
20742
20697
  process.stderr.write("Error: --opencode requires a path argument.\n");
@@ -20762,7 +20717,7 @@ async function runInitOpencodeFlow(args) {
20762
20717
  return cliExit(EXIT_CODES.SUCCESS);
20763
20718
  }
20764
20719
  async function renderOpencodeValidate(opencodePath) {
20765
- const { runOpencodeValidate } = await import("./init-opencode-L3NT524E.js");
20720
+ const { runOpencodeValidate } = await import("./init-opencode-4H2VPN23.js");
20766
20721
  const result = await runOpencodeValidate(opencodePath);
20767
20722
  if (!result.ok) {
20768
20723
  process.stderr.write(`init --opencode --validate: ${result.reason ?? "failed"}
@@ -20801,7 +20756,7 @@ async function handleSetupCommandAsync(args) {
20801
20756
  return cliExitFromStatus(exitCode);
20802
20757
  }
20803
20758
  async function runCustomApiSetup(args) {
20804
- const { configureCustomApi } = await import("./setup-custom-api-W7EDVKWR.js");
20759
+ const { configureCustomApi } = await import("./setup-custom-api-NJGCRIRO.js");
20805
20760
  const baseUrl = args.options.customApi;
20806
20761
  if (baseUrl === void 0) return EXIT_CODES.SERVER_START_FAILED;
20807
20762
  const input = {
@@ -22534,7 +22489,7 @@ function checkCircularDependencies(workflow) {
22534
22489
  var defaultStubFactory = {
22535
22490
  createAgentStub(agentType, action) {
22536
22491
  return async (inputs) => {
22537
- await new Promise((resolve13) => setTimeout(resolve13, 10));
22492
+ await new Promise((resolve14) => setTimeout(resolve14, 10));
22538
22493
  return {
22539
22494
  stepId: `${agentType}-${action}`,
22540
22495
  status: "success",
@@ -23162,7 +23117,10 @@ var ACTION_BY_CATEGORY = {
23162
23117
  consensus: "investigate",
23163
23118
  // #3852: a deprecation/consolidation candidate is a human decision, never an
23164
23119
  // autonomous code change — investigate only (Epic D ratification path).
23165
- "tool-fitness": "investigate"
23120
+ "tool-fitness": "investigate",
23121
+ // #3692/#3246: a perf regression needs root-cause diagnosis before any change —
23122
+ // investigate only; the surfaced signal never auto-applies a fix.
23123
+ "perf-regression": "investigate"
23166
23124
  };
23167
23125
  function clip(s, max) {
23168
23126
  return s.length > max ? s.slice(0, max) : s;
@@ -23343,8 +23301,16 @@ var RemediationStepSchema = z9.object({
23343
23301
  var RemediationPlanSchema = z9.object({
23344
23302
  /** Source signal key (mirrors ImprovementSignal.signalKey). */
23345
23303
  signalKey: z9.string().min(1).max(200),
23346
- /** Signal category (mirrors SignalCategory; 'tool-fitness' added #3852). */
23347
- category: z9.enum(["routing", "tech-debt", "bug", "security", "consensus", "tool-fitness"]),
23304
+ /** Signal category (mirrors SignalCategory; 'tool-fitness' #3852, 'perf-regression' #3692). */
23305
+ category: z9.enum([
23306
+ "routing",
23307
+ "tech-debt",
23308
+ "bug",
23309
+ "security",
23310
+ "consensus",
23311
+ "tool-fitness",
23312
+ "perf-regression"
23313
+ ]),
23348
23314
  summary: z9.string().min(1).max(1e3),
23349
23315
  steps: z9.array(RemediationStepSchema).min(1).max(20)
23350
23316
  }).strict();
@@ -23428,13 +23394,13 @@ function makeProposalPrImplementAdapter(opts) {
23428
23394
  };
23429
23395
  }
23430
23396
  function makeGitWorktreeOps(repoRoot) {
23431
- const git = async (args, cwd) => {
23397
+ const git2 = async (args, cwd) => {
23432
23398
  await execFileAsync4("git", [...args], { cwd });
23433
23399
  };
23434
23400
  return {
23435
23401
  async addWorktree(branch, baseBranch) {
23436
23402
  const path21 = join19(repoRoot, ".nexus-worktrees", branch.replace(/\//g, "_"));
23437
- await git(["worktree", "add", "-b", branch, path21, baseBranch], repoRoot);
23403
+ await git2(["worktree", "add", "-b", branch, path21, baseBranch], repoRoot);
23438
23404
  return path21;
23439
23405
  },
23440
23406
  async writeFileIn(worktreePath, relPath, content) {
@@ -23443,14 +23409,14 @@ function makeGitWorktreeOps(repoRoot) {
23443
23409
  await writeFile6(abs, content, "utf8");
23444
23410
  },
23445
23411
  async commitAll(worktreePath, message) {
23446
- await git(["add", "-A"], worktreePath);
23447
- await git(["commit", "-m", message], worktreePath);
23412
+ await git2(["add", "-A"], worktreePath);
23413
+ await git2(["commit", "-m", message], worktreePath);
23448
23414
  },
23449
23415
  async pushBranch(worktreePath, branch) {
23450
- await git(["push", "-u", "origin", branch], worktreePath);
23416
+ await git2(["push", "-u", "origin", branch], worktreePath);
23451
23417
  },
23452
23418
  async removeWorktree(worktreePath) {
23453
- await git(["worktree", "remove", worktreePath, "--force"], repoRoot);
23419
+ await git2(["worktree", "remove", worktreePath, "--force"], repoRoot);
23454
23420
  }
23455
23421
  };
23456
23422
  }
@@ -23632,6 +23598,689 @@ function buildAutoRemediationDeps(opts = {}) {
23632
23598
  };
23633
23599
  }
23634
23600
 
23601
+ // src/mcp/tools/codepr-soak-consumer.ts
23602
+ import { createHash as createHash4 } from "crypto";
23603
+
23604
+ // src/mcp/tools/codepr-orchestrator.ts
23605
+ import { createHash as createHash3 } from "crypto";
23606
+ import { mkdtempSync, mkdirSync as mkdirSync6, writeFileSync as writeFileSync8, rmSync as rmSync2, realpathSync as realpathSync2 } from "fs";
23607
+ import { tmpdir } from "os";
23608
+ import { dirname as dirname13, join as join20 } from "path";
23609
+ import { execFileSync as execFileSync3 } from "child_process";
23610
+ import { z as z12 } from "zod";
23611
+
23612
+ // src/mcp/tools/codepr-guards.ts
23613
+ import { realpathSync } from "fs";
23614
+ import { isAbsolute as isAbsolute4, resolve as resolve13, relative as relative5, sep as sep3, dirname as dirname12, basename as basename5 } from "path";
23615
+ import { z as z11 } from "zod";
23616
+ function deny(reason, detail) {
23617
+ return { ok: false, reason, detail };
23618
+ }
23619
+ function errnoCode(err2) {
23620
+ if (err2 !== null && typeof err2 === "object" && "code" in err2) {
23621
+ const code = err2.code;
23622
+ return typeof code === "string" ? code : void 0;
23623
+ }
23624
+ return void 0;
23625
+ }
23626
+ function confinePath(worktreeRoot, candidatePath, realpath = realpathSync) {
23627
+ if (!isAbsolute4(worktreeRoot)) {
23628
+ return deny("path_escape", "worktreeRoot must be an absolute path");
23629
+ }
23630
+ let resolvedRoot;
23631
+ try {
23632
+ resolvedRoot = realpath(worktreeRoot);
23633
+ } catch {
23634
+ return deny("path_escape", "worktreeRoot could not be resolved (fail-closed)");
23635
+ }
23636
+ const joined = isAbsolute4(candidatePath) ? candidatePath : resolve13(resolvedRoot, candidatePath);
23637
+ const reassembled = resolveNewFilePath(joined, realpath);
23638
+ if (reassembled === void 0) {
23639
+ return deny("path_escape", "candidate path could not be resolved (fail-closed)");
23640
+ }
23641
+ if (!isWithin(resolvedRoot, reassembled)) {
23642
+ return deny("path_escape", "resolved path is outside the worktree root");
23643
+ }
23644
+ return { ok: true, resolvedPath: reassembled };
23645
+ }
23646
+ function resolveNewFilePath(joined, realpath) {
23647
+ let existing = joined;
23648
+ const trailing = [];
23649
+ for (; ; ) {
23650
+ try {
23651
+ existing = realpath(existing);
23652
+ break;
23653
+ } catch (err2) {
23654
+ if (errnoCode(err2) !== "ENOENT") return void 0;
23655
+ const parent = dirname12(existing);
23656
+ if (parent === existing) return void 0;
23657
+ trailing.push(basename5(existing));
23658
+ existing = parent;
23659
+ }
23660
+ }
23661
+ return trailing.length === 0 ? existing : resolve13(existing, ...trailing.reverse());
23662
+ }
23663
+ function isWithin(parent, child) {
23664
+ if (child === parent) return true;
23665
+ const rel = relative5(parent, child);
23666
+ if (rel === "") return true;
23667
+ if (rel === ".." || rel.startsWith(".." + sep3)) return false;
23668
+ if (isAbsolute4(rel)) return false;
23669
+ return true;
23670
+ }
23671
+ function basenamePosix(relPathPosix) {
23672
+ const idx = relPathPosix.lastIndexOf("/");
23673
+ return idx === -1 ? relPathPosix : relPathPosix.slice(idx + 1);
23674
+ }
23675
+ var SELF_GUARD_MODULE_BASENAMES = [
23676
+ "codepr-guards",
23677
+ // this guard module (+ its tests / future dir) — prefix match
23678
+ "diff-secret-scan",
23679
+ // reused: pre-push secret scan
23680
+ "repo-root-detection",
23681
+ // reused: repo-root / path confinement source
23682
+ "audit-logger",
23683
+ // reused: hash-chained audit log
23684
+ "audit-types",
23685
+ // reused: audit schemas/interfaces the guard imports
23686
+ "improvement-enforce-readiness",
23687
+ // the enable-readiness module (shadow→enforce gate)
23688
+ "remediation-readiness-collector"
23689
+ // companion readiness collector
23690
+ ];
23691
+ function isSelfGuardPath(relPathPosix) {
23692
+ const base = basenamePosix(relPathPosix);
23693
+ for (const name of SELF_GUARD_MODULE_BASENAMES) {
23694
+ if (base === name) return true;
23695
+ if (base.startsWith(name + ".")) return true;
23696
+ if (relPathPosix === name || relPathPosix.startsWith(name + "/")) return true;
23697
+ if (relPathPosix.includes("/" + name + "/")) return true;
23698
+ }
23699
+ return false;
23700
+ }
23701
+ var SENSITIVE_PATH_RULES = [
23702
+ {
23703
+ category: "self_guard",
23704
+ description: "the adapter\u2019s own guard code + reused safety primitives (precondition B)",
23705
+ match: isSelfGuardPath
23706
+ },
23707
+ {
23708
+ category: "governance",
23709
+ description: "governance/** \u2014 voting, ratification, tier ledgers",
23710
+ match: (p) => p === "governance" || p.startsWith("governance/") || p.includes("/governance/")
23711
+ },
23712
+ {
23713
+ category: "workflow",
23714
+ description: ".github/workflows/** \u2014 CI/CD definitions",
23715
+ match: (p) => p.startsWith(".github/workflows/") || p.includes("/.github/workflows/")
23716
+ },
23717
+ {
23718
+ category: "codeowners",
23719
+ // `p` is already lower-cased by classifyPath (case-insensitive matching).
23720
+ description: "any CODEOWNERS file",
23721
+ match: (p) => basenamePosix(p) === "codeowners"
23722
+ },
23723
+ {
23724
+ category: "audit",
23725
+ description: "audit subsystem: src/audit/** (tamper-evidence \u2014 human-authored only)",
23726
+ match: (p) => p === "src/audit" || p.startsWith("src/audit/") || p.includes("/src/audit/")
23727
+ },
23728
+ {
23729
+ category: "authority",
23730
+ description: "auth/authority code: **/authority-*, **/auth/**",
23731
+ match: (p) => basenamePosix(p).startsWith("authority-") || p.includes("/auth/") || p.startsWith("auth/")
23732
+ },
23733
+ {
23734
+ category: "dependency_manifest",
23735
+ description: "dependency manifests: package.json, pnpm-lock.yaml, tsconfig*.json (precondition E)",
23736
+ match: (p) => {
23737
+ const base = basenamePosix(p);
23738
+ if (base === "package.json") return true;
23739
+ if (base === "pnpm-lock.yaml") return true;
23740
+ if (base.startsWith("tsconfig") && base.endsWith(".json")) return true;
23741
+ return false;
23742
+ }
23743
+ }
23744
+ ];
23745
+ function normalizeRelPath(relPath) {
23746
+ const adsIdx = relPath.indexOf("::");
23747
+ let p = adsIdx === -1 ? relPath : relPath.slice(0, adsIdx);
23748
+ p = p.replace(/\\/g, "/");
23749
+ p = p.replace(/\/{2,}/g, "/");
23750
+ while (p.startsWith("./")) p = p.slice(2);
23751
+ p = p.split("/").map((seg) => seg.replace(/[. ]+$/, "")).join("/");
23752
+ return p;
23753
+ }
23754
+ function classifyPath(relPath) {
23755
+ const p = normalizeRelPath(relPath).toLowerCase();
23756
+ for (const rule of SENSITIVE_PATH_RULES) {
23757
+ if (rule.match(p)) return { sensitive: true, category: rule.category };
23758
+ }
23759
+ return { sensitive: false };
23760
+ }
23761
+ var BlastRadiusLimitsSchema = z11.object({
23762
+ /** Max number of files the change may touch. Default 20. */
23763
+ maxFiles: z11.number().int().positive().default(20),
23764
+ /** Max total changed lines (added + removed across all files). Default 400. */
23765
+ maxLines: z11.number().int().positive().default(400)
23766
+ }).strict();
23767
+ var DEFAULT_BLAST_RADIUS_LIMITS = Object.freeze(
23768
+ BlastRadiusLimitsSchema.parse({})
23769
+ );
23770
+ function checkBlastRadius(changedFiles, limits = DEFAULT_BLAST_RADIUS_LIMITS) {
23771
+ const parsed = BlastRadiusLimitsSchema.safeParse(limits);
23772
+ if (!parsed.success) {
23773
+ return deny("blast_radius_exceeded", "invalid blast-radius limits (fail-closed)");
23774
+ }
23775
+ const { maxFiles, maxLines } = parsed.data;
23776
+ for (const f of changedFiles) {
23777
+ const cls = classifyPath(f.path);
23778
+ if (cls.sensitive) {
23779
+ return deny("sensitive_path", `changed file is sensitive (${cls.category}): ${f.path}`);
23780
+ }
23781
+ }
23782
+ const filesTouched = changedFiles.length;
23783
+ if (filesTouched > maxFiles) {
23784
+ return deny(
23785
+ "blast_radius_exceeded",
23786
+ `files touched ${String(filesTouched)} exceeds maxFiles ${String(maxFiles)}`
23787
+ );
23788
+ }
23789
+ let linesTouched = 0;
23790
+ for (const f of changedFiles) linesTouched += f.addedLines + f.removedLines;
23791
+ if (linesTouched > maxLines) {
23792
+ return deny(
23793
+ "blast_radius_exceeded",
23794
+ `changed lines ${String(linesTouched)} exceeds maxLines ${String(maxLines)}`
23795
+ );
23796
+ }
23797
+ return { ok: true, filesTouched, linesTouched };
23798
+ }
23799
+ function scanDiffOrDeny(diff) {
23800
+ const scan = scanForSecrets(diff);
23801
+ if (!scan.clean) {
23802
+ const summary = scan.findings.map((f) => `${f.pattern}@L${String(f.line)}`).join(", ");
23803
+ return deny(
23804
+ "secret_detected",
23805
+ `secret scan found ${String(scan.findings.length)} finding(s): ${summary}`
23806
+ );
23807
+ }
23808
+ return { ok: true, scan };
23809
+ }
23810
+ var AUTONOMOUS_ACTOR = {
23811
+ type: "system",
23812
+ id: "autonomous-code-pr",
23813
+ name: "Autonomous Code-PR Adapter (Stage 1, OFF)"
23814
+ };
23815
+ function auditAutonomousEvent(logger19, record) {
23816
+ try {
23817
+ logger19.log({
23818
+ category: "security",
23819
+ severity: record.decision === "abort" ? "warning" : "info",
23820
+ outcome: record.decision === "abort" ? "denied" : "success",
23821
+ action: `autonomous_code_pr.${record.decision}`,
23822
+ description: record.decision === "abort" ? `autonomous code-PR aborted (${record.abortReason ?? "unspecified"})` : "autonomous code-PR write-guards passed (would open PR)",
23823
+ actor: record.actor ?? AUTONOMOUS_ACTOR,
23824
+ resource: { type: "autonomous-run", id: record.runId, name: record.runId },
23825
+ metadata: {
23826
+ runId: record.runId,
23827
+ sourceSignalHash: record.sourceSignalHash,
23828
+ diffHash: record.diffHash,
23829
+ scanVerdict: record.scanVerdict,
23830
+ filesTouched: record.filesTouched,
23831
+ linesTouched: record.linesTouched,
23832
+ tokenIdentity: record.tokenIdentity,
23833
+ decision: record.decision,
23834
+ abortReason: record.abortReason ?? null
23835
+ }
23836
+ });
23837
+ } catch (err2) {
23838
+ const detail = err2 instanceof Error ? err2.message : String(err2);
23839
+ return deny("audit_append_failed", `audit append threw (fail-closed): ${detail}`);
23840
+ }
23841
+ return { ok: true };
23842
+ }
23843
+ var ResourceBudgetLimitsSchema = z11.object({
23844
+ /** Wall-clock ceiling in ms. Default 600000 (10 min). */
23845
+ maxWallClockMs: z11.number().int().positive().default(6e5),
23846
+ /** Token ceiling. Default 200000. */
23847
+ maxTokens: z11.number().int().positive().default(2e5),
23848
+ /** Tool-call ceiling. Default 200. */
23849
+ maxToolCalls: z11.number().int().positive().default(200)
23850
+ }).strict();
23851
+ var DEFAULT_RESOURCE_BUDGET_LIMITS = Object.freeze(
23852
+ ResourceBudgetLimitsSchema.parse({})
23853
+ );
23854
+ function checkResourceBudget(usage, limits = DEFAULT_RESOURCE_BUDGET_LIMITS) {
23855
+ const parsed = ResourceBudgetLimitsSchema.safeParse(limits);
23856
+ if (!parsed.success) {
23857
+ return deny("budget_exceeded", "invalid resource limits (fail-closed)");
23858
+ }
23859
+ const { maxWallClockMs, maxTokens, maxToolCalls } = parsed.data;
23860
+ if (usage.wallClockMs > maxWallClockMs) {
23861
+ return deny(
23862
+ "budget_exceeded",
23863
+ `wall-clock ${String(usage.wallClockMs)}ms exceeds ${String(maxWallClockMs)}ms`
23864
+ );
23865
+ }
23866
+ if (usage.tokens > maxTokens) {
23867
+ return deny("budget_exceeded", `tokens ${String(usage.tokens)} exceeds ${String(maxTokens)}`);
23868
+ }
23869
+ if (usage.toolCalls > maxToolCalls) {
23870
+ return deny(
23871
+ "budget_exceeded",
23872
+ `tool calls ${String(usage.toolCalls)} exceeds ${String(maxToolCalls)}`
23873
+ );
23874
+ }
23875
+ return { ok: true };
23876
+ }
23877
+ function evaluateWriteGuards(input) {
23878
+ for (const f of input.changedFiles) {
23879
+ const confined = runGuard(
23880
+ "confinePath",
23881
+ () => confinePath(input.worktreeRoot, f.path, input.realpath)
23882
+ );
23883
+ if (!confined.ok) return confined;
23884
+ }
23885
+ const blast = runGuard(
23886
+ "checkBlastRadius",
23887
+ () => checkBlastRadius(input.changedFiles, input.blastRadiusLimits)
23888
+ );
23889
+ if (!blast.ok) return blast;
23890
+ const secrets = runGuard("scanDiffOrDeny", () => scanDiffOrDeny(input.diff));
23891
+ if (!secrets.ok) return secrets;
23892
+ const budget = runGuard(
23893
+ "checkResourceBudget",
23894
+ () => checkResourceBudget(input.usage, input.resourceLimits)
23895
+ );
23896
+ if (!budget.ok) return budget;
23897
+ return { ok: true };
23898
+ }
23899
+ function runGuard(name, fn) {
23900
+ try {
23901
+ return fn();
23902
+ } catch (err2) {
23903
+ const message = err2 instanceof Error ? err2.message : String(err2);
23904
+ return deny("guard_error", `guard ${name} threw (fail-closed): ${message}`);
23905
+ }
23906
+ }
23907
+
23908
+ // src/mcp/tools/codepr-orchestrator.ts
23909
+ var ProposedChangeSchema = z12.object({
23910
+ /** Repo-relative path the change would write. */
23911
+ relPath: z12.string().min(1),
23912
+ /** The full new file content. */
23913
+ newContent: z12.string()
23914
+ }).strict();
23915
+ var CodePrRunInputSchema = z12.object({
23916
+ /** Correlates all audit events for this run. */
23917
+ runId: z12.string().min(1),
23918
+ /** Hash of the source signal (fitness/improvement) that triggered the run. */
23919
+ sourceSignalHash: z12.string().min(1),
23920
+ /** The proposed change set. */
23921
+ changes: z12.array(ProposedChangeSchema).min(1)
23922
+ }).strict();
23923
+ var ORCHESTRATOR_USAGE_ZERO = { wallClockMs: 0, tokens: 0, toolCalls: 0 };
23924
+ function sha256(s) {
23925
+ return createHash3("sha256").update(s).digest("hex");
23926
+ }
23927
+ function git(cwd, args) {
23928
+ return execFileSync3("git", [...args], { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
23929
+ }
23930
+ function parseNumstat(numstat) {
23931
+ const files = [];
23932
+ for (const line of numstat.split("\n")) {
23933
+ if (line.trim() === "") continue;
23934
+ const parts = line.split(" ");
23935
+ if (parts.length < 3) continue;
23936
+ const added = parts[0] === "-" ? 0 : Number.parseInt(parts[0] ?? "0", 10);
23937
+ const removed = parts[1] === "-" ? 0 : Number.parseInt(parts[1] ?? "0", 10);
23938
+ const path21 = parts.slice(2).join(" ");
23939
+ files.push({
23940
+ path: path21,
23941
+ addedLines: Number.isFinite(added) ? added : 0,
23942
+ removedLines: Number.isFinite(removed) ? removed : 0
23943
+ });
23944
+ }
23945
+ return files;
23946
+ }
23947
+ function denied(reason, detail, auditRecorded) {
23948
+ return { ok: false, reason, detail, auditRecorded };
23949
+ }
23950
+ function auditAbort(logger19, a) {
23951
+ const res = auditAutonomousEvent(logger19, {
23952
+ runId: a.input.runId,
23953
+ sourceSignalHash: a.input.sourceSignalHash,
23954
+ diffHash: a.diffHash,
23955
+ scanVerdict: a.reason === "secret_detected" ? "secret_detected" : "clean",
23956
+ filesTouched: a.filesTouched,
23957
+ linesTouched: a.linesTouched,
23958
+ tokenIdentity: "none",
23959
+ decision: "abort",
23960
+ abortReason: a.reason
23961
+ });
23962
+ return res.ok;
23963
+ }
23964
+ function precheckChanges(worktreeRoot, run, logger19) {
23965
+ for (const change of run.changes) {
23966
+ const confined = confinePath(worktreeRoot, change.relPath);
23967
+ if (!confined.ok) {
23968
+ const recorded = auditAbort(logger19, {
23969
+ input: run,
23970
+ reason: confined.reason,
23971
+ diffHash: sha256(""),
23972
+ filesTouched: 0,
23973
+ linesTouched: 0
23974
+ });
23975
+ return denied(confined.reason, confined.detail, recorded);
23976
+ }
23977
+ const cls = classifyPath(change.relPath);
23978
+ if (cls.sensitive) {
23979
+ const recorded = auditAbort(logger19, {
23980
+ input: run,
23981
+ reason: "sensitive_path",
23982
+ diffHash: sha256(""),
23983
+ filesTouched: 0,
23984
+ linesTouched: 0
23985
+ });
23986
+ return denied("sensitive_path", `sensitive path (${cls.category}): ${change.relPath}`, recorded);
23987
+ }
23988
+ }
23989
+ return void 0;
23990
+ }
23991
+ function applyChanges(worktreeRoot, run) {
23992
+ for (const change of run.changes) {
23993
+ const confined = confinePath(worktreeRoot, change.relPath);
23994
+ if (!confined.ok) throw new Error(`apply: ${confined.detail}`);
23995
+ mkdirSync6(dirname13(confined.resolvedPath), { recursive: true });
23996
+ writeFileSync8(confined.resolvedPath, change.newContent);
23997
+ }
23998
+ }
23999
+ function realizeDiff(worktreeRoot) {
24000
+ git(worktreeRoot, ["add", "-A"]);
24001
+ const diffText = git(worktreeRoot, ["diff", "--cached"]);
24002
+ const changedFiles = parseNumstat(git(worktreeRoot, ["diff", "--cached", "--numstat"]));
24003
+ let linesTouched = 0;
24004
+ for (const f of changedFiles) linesTouched += f.addedLines + f.removedLines;
24005
+ return { diffText, diffHash: sha256(diffText), changedFiles, linesTouched };
24006
+ }
24007
+ function runGuardsAndPlan(args, logger19) {
24008
+ const { worktreeRoot, run, realized } = args;
24009
+ const verdict = evaluateWriteGuards({
24010
+ worktreeRoot,
24011
+ changedFiles: realized.changedFiles,
24012
+ diff: realized.diffText,
24013
+ usage: args.usage,
24014
+ blastRadiusLimits: args.blastRadiusLimits,
24015
+ resourceLimits: args.resourceLimits
24016
+ });
24017
+ if (!verdict.ok) {
24018
+ const recorded = auditAbort(logger19, {
24019
+ input: run,
24020
+ reason: verdict.reason,
24021
+ diffHash: realized.diffHash,
24022
+ filesTouched: realized.changedFiles.length,
24023
+ linesTouched: realized.linesTouched
24024
+ });
24025
+ return denied(verdict.reason, verdict.detail, recorded);
24026
+ }
24027
+ const plan = {
24028
+ branchName: `auto/codepr/${run.runId}`,
24029
+ title: `auto code-PR (dry-run, NO push) for run ${run.runId}`,
24030
+ files: realized.changedFiles.map((f) => ({
24031
+ path: f.path,
24032
+ addedLines: f.addedLines,
24033
+ removedLines: f.removedLines
24034
+ })),
24035
+ filesTouched: realized.changedFiles.length,
24036
+ linesTouched: realized.linesTouched,
24037
+ diffHash: realized.diffHash
24038
+ };
24039
+ const audit = auditAutonomousEvent(logger19, {
24040
+ runId: run.runId,
24041
+ sourceSignalHash: run.sourceSignalHash,
24042
+ diffHash: realized.diffHash,
24043
+ scanVerdict: "clean",
24044
+ filesTouched: plan.filesTouched,
24045
+ linesTouched: plan.linesTouched,
24046
+ tokenIdentity: "none",
24047
+ decision: "would_open_pr"
24048
+ });
24049
+ if (!audit.ok) {
24050
+ return denied(audit.reason, audit.detail, false);
24051
+ }
24052
+ return { ok: true, plan, auditRecorded: true };
24053
+ }
24054
+ function runInWorktree(run, logger19, options, handle) {
24055
+ const fault = options.faultInjector;
24056
+ const repoRoot = options.repoRoot ?? process.cwd();
24057
+ handle.tempParent = realpathSync2(mkdtempSync(join20(tmpdir(), "codepr-orchestrator-")));
24058
+ handle.worktreeRoot = join20(handle.tempParent, "wt");
24059
+ git(repoRoot, ["worktree", "add", "--detach", handle.worktreeRoot]);
24060
+ fault?.("after-worktree");
24061
+ const precheck = precheckChanges(handle.worktreeRoot, run, logger19);
24062
+ if (precheck !== void 0) return precheck;
24063
+ applyChanges(handle.worktreeRoot, run);
24064
+ fault?.("after-apply");
24065
+ const realized = realizeDiff(handle.worktreeRoot);
24066
+ fault?.("after-diff");
24067
+ return runGuardsAndPlan(
24068
+ {
24069
+ worktreeRoot: handle.worktreeRoot,
24070
+ run,
24071
+ realized,
24072
+ usage: options.usage ?? ORCHESTRATOR_USAGE_ZERO,
24073
+ blastRadiusLimits: options.blastRadiusLimits,
24074
+ resourceLimits: options.resourceLimits
24075
+ },
24076
+ logger19
24077
+ );
24078
+ }
24079
+ function discardWorktree(repoRoot, handle) {
24080
+ if (handle.worktreeRoot !== void 0) {
24081
+ try {
24082
+ git(repoRoot, ["worktree", "remove", "--force", handle.worktreeRoot]);
24083
+ } catch {
24084
+ }
24085
+ }
24086
+ if (handle.tempParent !== void 0) {
24087
+ try {
24088
+ rmSync2(handle.tempParent, { recursive: true, force: true });
24089
+ } catch {
24090
+ }
24091
+ }
24092
+ }
24093
+ function planCodePrRun(input, logger19, options = {}) {
24094
+ const parsed = CodePrRunInputSchema.safeParse(input);
24095
+ if (!parsed.success) {
24096
+ return denied("guard_error", "invalid code-PR run input (fail-closed)", false);
24097
+ }
24098
+ const run = parsed.data;
24099
+ const repoRoot = options.repoRoot ?? process.cwd();
24100
+ const handle = {};
24101
+ try {
24102
+ return runInWorktree(run, logger19, options, handle);
24103
+ } catch (err2) {
24104
+ const message = err2 instanceof Error ? err2.message : String(err2);
24105
+ let recorded = false;
24106
+ try {
24107
+ recorded = auditAbort(logger19, {
24108
+ input: run,
24109
+ reason: "guard_error",
24110
+ diffHash: sha256(""),
24111
+ filesTouched: 0,
24112
+ linesTouched: 0
24113
+ });
24114
+ } catch {
24115
+ recorded = false;
24116
+ }
24117
+ return denied("guard_error", `orchestrator failed (fail-closed): ${message}`, recorded);
24118
+ } finally {
24119
+ discardWorktree(repoRoot, handle);
24120
+ }
24121
+ }
24122
+
24123
+ // src/mcp/tools/codepr-soak-store.ts
24124
+ import { z as z13 } from "zod";
24125
+ var CodePrSoakRecordSchema = z13.object({
24126
+ /** ISO-8601 capture time. */
24127
+ timestamp: z13.string(),
24128
+ /** Correlates the data point to the dry-run's orchestrator runId. */
24129
+ runId: z13.string(),
24130
+ /** The improvement signal's stable key that triggered the dry-run. */
24131
+ signalKey: z13.string(),
24132
+ /** True when the dry-run plan succeeded with ZERO guard denial. */
24133
+ green: z13.boolean(),
24134
+ /** The guard denial reason when `green` is false; omitted for a green plan. */
24135
+ denialReason: z13.string().optional(),
24136
+ /** Files the dry-run plan touched (0 on denial before the diff was realized). */
24137
+ filesTouched: z13.number().int().nonnegative()
24138
+ }).strict();
24139
+ var CODEPR_SOAK_MAX_RECORDS = 1e4;
24140
+ function getCodePrSoakFile() {
24141
+ return nexusDataPath("learning", "codepr-guards-soak.jsonl");
24142
+ }
24143
+ function createCodePrSoakSink(filePath = getCodePrSoakFile(), maxRecords = CODEPR_SOAK_MAX_RECORDS) {
24144
+ const store = new JsonlStore({
24145
+ filePath,
24146
+ schema: CodePrSoakRecordSchema,
24147
+ maxRecords,
24148
+ component: "CodePrSoakSink"
24149
+ });
24150
+ return {
24151
+ record(record) {
24152
+ store.append(record);
24153
+ },
24154
+ getRecords() {
24155
+ return store.all();
24156
+ }
24157
+ };
24158
+ }
24159
+ var soakSingleton;
24160
+ function getCodePrSoakSink() {
24161
+ soakSingleton ??= createCodePrSoakSink();
24162
+ return soakSingleton;
24163
+ }
24164
+ function greenCodePrSoakRecord(args) {
24165
+ return {
24166
+ timestamp: new Date(getTimeProvider().now()).toISOString(),
24167
+ runId: args.runId,
24168
+ signalKey: args.signalKey,
24169
+ green: true,
24170
+ filesTouched: args.filesTouched
24171
+ };
24172
+ }
24173
+ function deniedCodePrSoakRecord(args) {
24174
+ return {
24175
+ timestamp: new Date(getTimeProvider().now()).toISOString(),
24176
+ runId: args.runId,
24177
+ signalKey: args.signalKey,
24178
+ green: false,
24179
+ denialReason: args.denialReason,
24180
+ filesTouched: 0
24181
+ };
24182
+ }
24183
+
24184
+ // src/mcp/tools/codepr-soak-consumer.ts
24185
+ var CODE_TOUCHING_KINDS = /* @__PURE__ */ new Set([
24186
+ "add-test",
24187
+ "refactor",
24188
+ "update-docs",
24189
+ "fix-bug"
24190
+ ]);
24191
+ function planTouchesCode(plan) {
24192
+ return plan.steps.some((s) => CODE_TOUCHING_KINDS.has(s.kind));
24193
+ }
24194
+ function placeholderPathFor(plan, kind) {
24195
+ const h = createHash4("sha256").update(`${plan.signalKey}:${kind}`).digest("hex").slice(0, 12);
24196
+ return `src/__codepr_soak__/${kind}-${h}.ts`;
24197
+ }
24198
+ function deriveProposedChanges(plan) {
24199
+ const seen = /* @__PURE__ */ new Set();
24200
+ const changes = [];
24201
+ for (const step of plan.steps) {
24202
+ if (!CODE_TOUCHING_KINDS.has(step.kind)) continue;
24203
+ const path21 = step.targetPath !== void 0 && step.targetPath !== "" ? step.targetPath : placeholderPathFor(plan, step.kind);
24204
+ if (seen.has(path21)) continue;
24205
+ seen.add(path21);
24206
+ changes.push({
24207
+ relPath: path21,
24208
+ newContent: `// codepr soak dry-run placeholder for ${plan.signalKey} (${step.kind})
24209
+ `
24210
+ });
24211
+ }
24212
+ return changes;
24213
+ }
24214
+ function loggerBackedAuditLogger(logger19) {
24215
+ return {
24216
+ log: (input) => {
24217
+ logger19.debug("codepr soak dry-run audit event", {
24218
+ action: input.action,
24219
+ outcome: input.outcome
24220
+ });
24221
+ },
24222
+ logToolInvocation: () => {
24223
+ },
24224
+ logPolicyDecision: () => {
24225
+ },
24226
+ logSecurityEvent: () => {
24227
+ },
24228
+ logRateLimitViolation: () => {
24229
+ },
24230
+ logTierTransition: () => {
24231
+ },
24232
+ flush: () => Promise.resolve(),
24233
+ close: () => Promise.resolve()
24234
+ };
24235
+ }
24236
+ function soakRunId(plan) {
24237
+ return `codepr-soak-${createHash4("sha256").update(plan.signalKey).digest("hex").slice(0, 16)}`;
24238
+ }
24239
+ function sourceSignalHash(plan) {
24240
+ return createHash4("sha256").update(plan.signalKey).digest("hex");
24241
+ }
24242
+ function runCodePrSoak(plan, inject = {}) {
24243
+ const logger19 = inject.logger ?? createLogger({ tool: "codepr-soak" });
24244
+ try {
24245
+ soakOnce(plan, inject, logger19);
24246
+ } catch (err2) {
24247
+ logger19.warn("codepr soak step failed (swallowed; cycle proceeds)", {
24248
+ signalKey: plan.signalKey,
24249
+ error: getErrorMessage(err2)
24250
+ });
24251
+ }
24252
+ }
24253
+ function soakOnce(plan, inject, logger19) {
24254
+ if (!planTouchesCode(plan)) return;
24255
+ const changes = deriveProposedChanges(plan);
24256
+ if (changes.length === 0) return;
24257
+ const runId = soakRunId(plan);
24258
+ const planRun = inject.planRun ?? planCodePrRun;
24259
+ const result = planRun(
24260
+ { runId, sourceSignalHash: sourceSignalHash(plan), changes },
24261
+ inject.auditLogger ?? loggerBackedAuditLogger(logger19),
24262
+ inject.orchestratorOptions ?? {}
24263
+ );
24264
+ const sink = inject.sink ?? getCodePrSoakSink();
24265
+ if (result.ok) {
24266
+ sink.record(
24267
+ greenCodePrSoakRecord({ runId, signalKey: plan.signalKey, filesTouched: result.plan.filesTouched })
24268
+ );
24269
+ logger19.debug("codepr soak: green dry-run recorded", {
24270
+ signalKey: plan.signalKey,
24271
+ filesTouched: result.plan.filesTouched
24272
+ });
24273
+ } else {
24274
+ sink.record(
24275
+ deniedCodePrSoakRecord({ runId, signalKey: plan.signalKey, denialReason: result.reason })
24276
+ );
24277
+ logger19.debug("codepr soak: denied dry-run recorded (streak reset)", {
24278
+ signalKey: plan.signalKey,
24279
+ reason: result.reason
24280
+ });
24281
+ }
24282
+ }
24283
+
23635
24284
  // src/mcp/tools/improvement-remediation-guard.ts
23636
24285
  var DEFAULT_REMEDIATION_GUARD_CONFIG = {
23637
24286
  cooldownMs: 6 * 60 * 60 * 1e3,
@@ -23974,6 +24623,17 @@ ${renderPlanAsResearch(plan)}`;
23974
24623
  }
23975
24624
  return null;
23976
24625
  }
24626
+ function firePlanObserver(deps, signal, plan) {
24627
+ if (deps.onPlanProduced === void 0) return;
24628
+ try {
24629
+ deps.onPlanProduced(signal, plan);
24630
+ } catch (err2) {
24631
+ deps.logger?.warn("onPlanProduced observer threw (swallowed)", {
24632
+ signalKey: signal.signalKey,
24633
+ error: err2 instanceof Error ? err2.message : String(err2)
24634
+ });
24635
+ }
24636
+ }
23977
24637
  async function executeOne(signal, deps, mode, ctx) {
23978
24638
  const { guard, now, requirement } = ctx;
23979
24639
  const ledger = new CapabilityLedger();
@@ -23991,6 +24651,7 @@ async function executeOne(signal, deps, mode, ctx) {
23991
24651
  signalKey: signal.signalKey,
23992
24652
  detail: `${String(plan.steps.length)} steps`
23993
24653
  });
24654
+ firePlanObserver(deps, signal, plan);
23994
24655
  const protectedPaths = planTouchesProtectedPath(plan);
23995
24656
  if (protectedPaths.protected) {
23996
24657
  const reason = `protected path(s) ${protectedPaths.paths.join(", ")} \u2014 human attestation required`;
@@ -24024,7 +24685,7 @@ async function runAutoRemediationCycle(config = {}, inject = {}) {
24024
24685
  logger19.info(`auto-remediation cycle: ${mode} over ${String(signals.length)} signals`);
24025
24686
  if (mode === "audit") {
24026
24687
  const collector = buildSoakCollector(signals, inject);
24027
- const soakDeps = withSoakAudit(deps, collector);
24688
+ const soakDeps = withCodePrSoak(withSoakAudit(deps, collector), inject);
24028
24689
  try {
24029
24690
  return await runAutoRemediation(signals, soakDeps, { mode });
24030
24691
  } finally {
@@ -24033,6 +24694,15 @@ async function runAutoRemediationCycle(config = {}, inject = {}) {
24033
24694
  }
24034
24695
  return runAutoRemediation(signals, deps, { mode });
24035
24696
  }
24697
+ function withCodePrSoak(deps, inject) {
24698
+ const runSoak = inject.runCodePrSoak ?? runCodePrSoak;
24699
+ return {
24700
+ ...deps,
24701
+ onPlanProduced: (_signal, plan) => {
24702
+ runSoak(plan, inject.codePrSoak);
24703
+ }
24704
+ };
24705
+ }
24036
24706
  function buildSoakCollector(signals, inject) {
24037
24707
  const meta = /* @__PURE__ */ new Map();
24038
24708
  for (const s of signals) {
@@ -24204,18 +24874,18 @@ async function handleRemediationReviewCommand(args) {
24204
24874
  }
24205
24875
 
24206
24876
  // src/cli/migrate-command.ts
24207
- import { cpSync, existsSync as existsSync24, mkdirSync as mkdirSync6, readdirSync as readdirSync3 } from "fs";
24877
+ import { cpSync, existsSync as existsSync23, mkdirSync as mkdirSync7, readdirSync as readdirSync3 } from "fs";
24208
24878
  import { homedir } from "os";
24209
- import { join as join20 } from "path";
24879
+ import { join as join21 } from "path";
24210
24880
  var logger18 = createLogger({ component: "migrate-command" });
24211
- var HOMEDIR_DEFAULT_BASE = join20(homedir(), ".nexus-agents");
24881
+ var HOMEDIR_DEFAULT_BASE = join21(homedir(), ".nexus-agents");
24212
24882
  function countItems(dir) {
24213
- if (!existsSync24(dir)) return 0;
24883
+ if (!existsSync23(dir)) return 0;
24214
24884
  try {
24215
24885
  const entries = readdirSync3(dir, { withFileTypes: true });
24216
24886
  let n = 0;
24217
24887
  for (const e of entries) {
24218
- const p = join20(dir, e.name);
24888
+ const p = join21(dir, e.name);
24219
24889
  if (e.isDirectory()) {
24220
24890
  n += countItems(p);
24221
24891
  } else {
@@ -24257,7 +24927,7 @@ function checkEarlyExits(fromBase, toBase, dryRun) {
24257
24927
  summary: "No git repo detected from cwd. Run from inside a repo or pass --to <path> to choose an explicit destination."
24258
24928
  };
24259
24929
  }
24260
- if (!existsSync24(fromBase)) {
24930
+ if (!existsSync23(fromBase)) {
24261
24931
  return {
24262
24932
  fromBase,
24263
24933
  toBase,
@@ -24270,8 +24940,8 @@ function checkEarlyExits(fromBase, toBase, dryRun) {
24270
24940
  return null;
24271
24941
  }
24272
24942
  function planAndExecuteEntry(name, fromBase, toBase, perRepoSet, dryRun) {
24273
- const source = join20(fromBase, name);
24274
- const target = join20(toBase, name);
24943
+ const source = join21(fromBase, name);
24944
+ const target = join21(toBase, name);
24275
24945
  if (!perRepoSet.has(name)) {
24276
24946
  return { subdir: name, status: "skipped-not-per-repo", source, target: "", itemsCopied: 0 };
24277
24947
  }
@@ -24279,11 +24949,11 @@ function planAndExecuteEntry(name, fromBase, toBase, perRepoSet, dryRun) {
24279
24949
  if (items === 0) {
24280
24950
  return { subdir: name, status: "skipped-empty", source, target, itemsCopied: 0 };
24281
24951
  }
24282
- if (existsSync24(target) && readdirSync3(target).length > 0) {
24952
+ if (existsSync23(target) && readdirSync3(target).length > 0) {
24283
24953
  return { subdir: name, status: "skipped-exists", source, target, itemsCopied: 0 };
24284
24954
  }
24285
24955
  if (!dryRun) {
24286
- mkdirSync6(toBase, { recursive: true });
24956
+ mkdirSync7(toBase, { recursive: true });
24287
24957
  cpSync(source, target, { recursive: true, errorOnExist: false });
24288
24958
  }
24289
24959
  return { subdir: name, status: "copied", source, target, itemsCopied: items };
@@ -24291,7 +24961,7 @@ function planAndExecuteEntry(name, fromBase, toBase, perRepoSet, dryRun) {
24291
24961
  function resolveDefaultTarget(cwd) {
24292
24962
  const repoRoot = findRepoRoot(cwd);
24293
24963
  if (repoRoot === null) return null;
24294
- return join20(repoRoot, ".nexus-agents");
24964
+ return join21(repoRoot, ".nexus-agents");
24295
24965
  }
24296
24966
  function formatMigrationResult(result) {
24297
24967
  if (!result.success) {
@@ -24332,6 +25002,32 @@ async function handleMigrateCommand(args) {
24332
25002
  return cliExit(result.success ? EXIT_CODES.SUCCESS : EXIT_CODES.SERVER_START_FAILED);
24333
25003
  }
24334
25004
 
25005
+ // src/cli/first-run-hint.ts
25006
+ import { existsSync as existsSync24, mkdirSync as mkdirSync8, writeFileSync as writeFileSync9 } from "fs";
25007
+ import { dirname as dirname14 } from "path";
25008
+ var HINT_SUPPRESSED_COMMANDS = /* @__PURE__ */ new Set(["version", "help", "setup"]);
25009
+ function firstRunMarkerPath() {
25010
+ return nexusSharedPath(".first-run-done");
25011
+ }
25012
+ function maybeShowFirstRunHint(command) {
25013
+ if (HINT_SUPPRESSED_COMMANDS.has(command)) return;
25014
+ if (!process.stderr.isTTY) return;
25015
+ const marker = firstRunMarkerPath();
25016
+ try {
25017
+ if (existsSync24(marker)) return;
25018
+ } catch {
25019
+ }
25020
+ process.stderr.write(
25021
+ "\x1B[36mnexus-agents\x1B[0m: First time? Run \x1B[1mnexus-agents setup\x1B[0m to configure.\n (This one-time hint is now dismissed.)\n"
25022
+ );
25023
+ try {
25024
+ mkdirSync8(dirname14(marker), { recursive: true });
25025
+ writeFileSync9(marker, `${(/* @__PURE__ */ new Date()).toISOString()}
25026
+ `, { flag: "w" });
25027
+ } catch {
25028
+ }
25029
+ }
25030
+
24335
25031
  // src/cli-commands.ts
24336
25032
  function printHelp(args) {
24337
25033
  const all = args?.options.all ?? false;
@@ -24454,6 +25150,7 @@ async function handleAsyncCommand(args) {
24454
25150
  }
24455
25151
  async function dispatchCommand(args) {
24456
25152
  initDataDirectories();
25153
+ maybeShowFirstRunHint(args.command);
24457
25154
  bootstrapStepNotifications({ mode: args.command === "server" ? "mcp-stdio" : "cli" });
24458
25155
  if (!handleSyncCommand(args)) {
24459
25156
  await handleAsyncCommand(args);
@@ -24463,7 +25160,6 @@ async function dispatchCommand(args) {
24463
25160
  // src/cli-command-help.ts
24464
25161
  var ORCHESTRATE_HELP = {
24465
25162
  command: "orchestrate",
24466
- description: "Execute a task using CLI tools (standalone mode). Routes to optimal model.",
24467
25163
  examples: [
24468
25164
  'nexus-agents orchestrate "Explain this function"',
24469
25165
  'nexus-agents orchestrate "Generate unit tests" --model=claude',
@@ -24486,7 +25182,6 @@ var ORCHESTRATE_HELP = {
24486
25182
  };
24487
25183
  var VOTE_HELP = {
24488
25184
  command: "vote",
24489
- description: "Run multi-agent consensus vote on a proposal (6 agents by default).",
24490
25185
  examples: [
24491
25186
  'nexus-agents vote --proposal "Add caching layer"',
24492
25187
  'nexus-agents vote -p "Migrate to PostgreSQL" -t supermajority',
@@ -24496,7 +25191,7 @@ var VOTE_HELP = {
24496
25191
  flags: [
24497
25192
  { flag: "-p, --proposal <text>", description: "Proposal text to vote on (required)" },
24498
25193
  { flag: "-t, --threshold <t>", description: "Threshold: majority, supermajority, unanimous" },
24499
- { flag: "--quick", description: "Use 3 agents instead of 6 for faster votes" },
25194
+ { flag: "--quick", description: "Use 3 agents instead of the full 7 for faster votes" },
24500
25195
  { flag: "--dry-run", description: "Simulate votes without agent execution" },
24501
25196
  { flag: "--timeout=<seconds>", description: "Timeout per vote in seconds", defaultValue: "90" },
24502
25197
  {
@@ -24509,7 +25204,6 @@ var VOTE_HELP = {
24509
25204
  };
24510
25205
  var EXPERT_HELP = {
24511
25206
  command: "expert",
24512
- description: "Manage expert agents. Subcommands: list, create, execute.",
24513
25207
  examples: ["nexus-agents expert list", "nexus-agents expert list --format=json"],
24514
25208
  flags: [
24515
25209
  {
@@ -24521,7 +25215,6 @@ var EXPERT_HELP = {
24521
25215
  };
24522
25216
  var WORKFLOW_HELP = {
24523
25217
  command: "workflow",
24524
- description: "Manage and run workflow templates. Subcommands: list, run.",
24525
25218
  examples: [
24526
25219
  "nexus-agents workflow list",
24527
25220
  `nexus-agents workflow run code-review --input='{"url":"https://github.com/o/r/pull/1"}'`,
@@ -24534,7 +25227,6 @@ var WORKFLOW_HELP = {
24534
25227
  };
24535
25228
  var DOCTOR_HELP = {
24536
25229
  command: "doctor",
24537
- description: "Check CLI installations, adapters, and system health.",
24538
25230
  examples: ["nexus-agents doctor", "nexus-agents doctor --deep", "nexus-agents doctor --fix"],
24539
25231
  flags: [
24540
25232
  { flag: "--deep", description: "Run deep health checks (adapter connectivity)" },
@@ -24544,7 +25236,6 @@ var DOCTOR_HELP = {
24544
25236
  };
24545
25237
  var MODE_HELP = {
24546
25238
  command: "mode",
24547
- description: "Inspect the detected invocation mode (server vs orchestrator), the signals that fed the decision, and the one-line reasoning. Useful for debugging unexpected modes in CI/containers.",
24548
25239
  examples: [
24549
25240
  "nexus-agents mode",
24550
25241
  "nexus-agents mode --format=json",
@@ -24560,7 +25251,6 @@ var MODE_HELP = {
24560
25251
  };
24561
25252
  var SETUP_HELP = {
24562
25253
  command: "setup",
24563
- description: "Configure MCP integration for Claude, Gemini, Codex, and OpenCode CLIs.",
24564
25254
  examples: [
24565
25255
  "nexus-agents setup",
24566
25256
  "nexus-agents setup --interactive",
@@ -24597,7 +25287,6 @@ var SETUP_HELP = {
24597
25287
  };
24598
25288
  var CONFIG_HELP = {
24599
25289
  command: "config",
24600
- description: "Manage nexus-agents configuration. Subcommands: init, get, set, list, reset, export, import.",
24601
25290
  examples: [
24602
25291
  "nexus-agents config init",
24603
25292
  "nexus-agents config get TIMEOUT_DEFAULTS.cliMs",
@@ -24617,7 +25306,6 @@ var CONFIG_HELP = {
24617
25306
  };
24618
25307
  var RESEARCH_HELP = {
24619
25308
  command: "research",
24620
- description: "Manage research registry and paper tracking. Subcommands: status, overlap, add, stats, refresh, check, index.",
24621
25309
  examples: [
24622
25310
  "nexus-agents research status",
24623
25311
  "nexus-agents research stats --format=json",
@@ -24632,7 +25320,6 @@ var RESEARCH_HELP = {
24632
25320
  };
24633
25321
  var FITNESS_AUDIT_HELP = {
24634
25322
  command: "fitness-audit",
24635
- description: "Run CLI orchestration fitness score audit. Target: 90+/100.",
24636
25323
  examples: [
24637
25324
  "nexus-agents fitness-audit",
24638
25325
  "nexus-agents fitness-audit --format=json",
@@ -24649,7 +25336,6 @@ var FITNESS_AUDIT_HELP = {
24649
25336
  };
24650
25337
  var REVIEW_HELP = {
24651
25338
  command: "review",
24652
- description: "Review a GitHub pull request (dogfooding mode).",
24653
25339
  examples: [
24654
25340
  "nexus-agents review https://github.com/owner/repo/pull/123",
24655
25341
  "nexus-agents review owner/repo#123 --dry-run",
@@ -24678,11 +25364,14 @@ function formatFlag(entry) {
24678
25364
  const defaultSuffix = entry.defaultValue !== void 0 ? ` (default: ${entry.defaultValue})` : "";
24679
25365
  return ` ${entry.flag.padEnd(28)} ${entry.description}${defaultSuffix}`;
24680
25366
  }
25367
+ function describe(command) {
25368
+ return getCommandDescription(command) ?? "";
25369
+ }
24681
25370
  function formatCommandHelp(command) {
24682
25371
  const entry = COMMAND_HELP.find((e) => e.command === command);
24683
25372
  if (entry === void 0) return void 0;
24684
25373
  const lines = [];
24685
- lines.push(`nexus-agents ${entry.command} -- ${entry.description}`);
25374
+ lines.push(`nexus-agents ${entry.command} -- ${describe(entry.command)}`);
24686
25375
  lines.push("");
24687
25376
  if (entry.flags !== void 0 && entry.flags.length > 0) {
24688
25377
  lines.push("FLAGS:");