nexus-agents 8.89.2 → 8.89.4

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 (127) hide show
  1. package/dist/{ast-rule-runner-AMZCLKRV.js → ast-rule-runner-NOWNF5QY.js} +3 -3
  2. package/dist/{child-mcp-config-7DSYI325.js → child-mcp-config-UBKF4SOL.js} +2 -2
  3. package/dist/{chunk-XU2SJKFK.js → chunk-2C5ABWLK.js} +2 -2
  4. package/dist/{chunk-SCXCJSTT.js → chunk-3E4BZR3V.js} +2 -2
  5. package/dist/{chunk-BJXSG5YL.js → chunk-4W4S6OBP.js} +4 -4
  6. package/dist/{chunk-Z5VUMKF5.js → chunk-5JZ635RM.js} +3 -3
  7. package/dist/{chunk-ZTTBGME2.js → chunk-5XCRXV43.js} +2 -2
  8. package/dist/{chunk-KQE7EFBF.js → chunk-6YQ55DOE.js} +5 -5
  9. package/dist/{chunk-AXBEG6VW.js → chunk-6ZPHMRJQ.js} +4 -4
  10. package/dist/{chunk-3PQIIMHN.js → chunk-DGW6C2PT.js} +60 -21
  11. package/dist/chunk-DGW6C2PT.js.map +1 -0
  12. package/dist/{chunk-OQB3XC5O.js → chunk-EZNIYU5T.js} +7 -2
  13. package/dist/{chunk-OQB3XC5O.js.map → chunk-EZNIYU5T.js.map} +1 -1
  14. package/dist/{chunk-CG7OSI5P.js → chunk-F3PIVN3B.js} +2 -2
  15. package/dist/{chunk-5GZ4UN5F.js → chunk-GLG667IV.js} +2 -2
  16. package/dist/{chunk-UDWZJY3V.js → chunk-GPEGBNGB.js} +2 -2
  17. package/dist/{chunk-JYKRCQSU.js → chunk-H7PL2D5A.js} +5 -5
  18. package/dist/{chunk-GYQIIAVM.js → chunk-K6IVHUEK.js} +3 -3
  19. package/dist/{chunk-5XZCL7QT.js → chunk-LBYA22G5.js} +11 -11
  20. package/dist/{chunk-3IBALX36.js → chunk-LVL6WCWK.js} +2 -2
  21. package/dist/{chunk-E6AJH4F4.js → chunk-NBVYSGSS.js} +37 -37
  22. package/dist/{chunk-GXBXZCY7.js → chunk-NRSAOTT7.js} +10 -10
  23. package/dist/{chunk-NZN3SWSZ.js → chunk-P2RI4DGX.js} +4 -3
  24. package/dist/{chunk-JYZNPK62.js → chunk-P5ND7MWI.js} +8 -8
  25. package/dist/{chunk-TRCYUQ4M.js → chunk-PEN5XFMP.js} +2 -2
  26. package/dist/{chunk-XJAGCUMD.js → chunk-R57JPKHJ.js} +2 -2
  27. package/dist/{chunk-4IV25ZUM.js → chunk-RQBI56JN.js} +2 -2
  28. package/dist/{chunk-6FFBX665.js → chunk-SFHIXQGK.js} +2 -2
  29. package/dist/{chunk-5UCGVAEZ.js → chunk-SXS2YQUK.js} +4 -4
  30. package/dist/{chunk-VM4HZT3B.js → chunk-TFZDHQ45.js} +4 -4
  31. package/dist/{chunk-JRZEB4OQ.js → chunk-U2C6V65K.js} +2 -2
  32. package/dist/{chunk-LZNYQYDU.js → chunk-UR2KFP6P.js} +2 -2
  33. package/dist/{chunk-EKZ6V7SE.js → chunk-XM2GVJPE.js} +7 -7
  34. package/dist/{chunk-HLXXP3CS.js → chunk-XS3IJG4V.js} +3 -3
  35. package/dist/{chunk-ILA4UGXI.js → chunk-YBW45NIZ.js} +2 -2
  36. package/dist/{chunk-PENEGF75.js → chunk-YG3UYPKL.js} +2 -2
  37. package/dist/{chunk-LFFXUHX3.js → chunk-YT7EP2B6.js} +2 -2
  38. package/dist/{chunk-TLFZPJOY.js → chunk-YYVBEHM3.js} +4 -4
  39. package/dist/{cli-circuit-breaker-MCQG3PQK.js → cli-circuit-breaker-IFVKXCHQ.js} +3 -3
  40. package/dist/cli.js +91 -68
  41. package/dist/cli.js.map +1 -1
  42. package/dist/{composite-router-QAYCHEFG.js → composite-router-7LFS4CMF.js} +2 -2
  43. package/dist/{consensus-vote-UHNEKOO7.js → consensus-vote-SA2KVDQA.js} +17 -17
  44. package/dist/{context-retriever-UXQCDDRY.js → context-retriever-V7OWZW7R.js} +8 -8
  45. package/dist/{doctor-deep-QRLRDFM4.js → doctor-deep-GJPTXS2N.js} +4 -3
  46. package/dist/{doctor-live-CUKBQSSH.js → doctor-live-ET5O7O2D.js} +10 -10
  47. package/dist/{expert-bridge-ZG2IA3RJ.js → expert-bridge-G656VGZG.js} +4 -4
  48. package/dist/{factory-RQEHJ4AW.js → factory-BQBFECEV.js} +9 -9
  49. package/dist/{factory-FPNYFKXU.js → factory-N34PTEMW.js} +5 -5
  50. package/dist/{improvement-review-N36SVUDG.js → improvement-review-YIXDCEX4.js} +5 -5
  51. package/dist/index.js +31 -31
  52. package/dist/{init-opencode-4QECASK4.js → init-opencode-33EU3PD6.js} +5 -5
  53. package/dist/issue-triage-URFEVDIX.js +16 -0
  54. package/dist/{pr-reviewer-helpers-RK5IT4US.js → pr-reviewer-helpers-ZDAJARQ7.js} +5 -5
  55. package/dist/{registry-command-MBZFFDWS.js → registry-command-AB7KP7DK.js} +2 -2
  56. package/dist/{repo-security-plan-W76YLC2M.js → repo-security-plan-YV3ZFKGO.js} +3 -3
  57. package/dist/{research-helpers-synthesize-GI5JFAQM.js → research-helpers-synthesize-EOHUBGH3.js} +4 -4
  58. package/dist/{routing-memory-WLCUOPDE.js → routing-memory-34JWGSAI.js} +2 -2
  59. package/dist/{session-memory-HU3XMQEH.js → session-memory-QGIJCM7P.js} +3 -3
  60. package/dist/{setup-config-XA756R2O.js → setup-config-3KBMBPCN.js} +3 -3
  61. package/dist/{setup-custom-api-ETBGOE7O.js → setup-custom-api-652FK232.js} +4 -4
  62. package/dist/setup-data-dir-XJMN4ALO.js +32 -0
  63. package/dist/{tool-memory-7XMQAQQM.js → tool-memory-SPPCBLKQ.js} +5 -5
  64. package/dist/{unified-registry-LR4OCUFI.js → unified-registry-ZOLSOVYN.js} +10 -10
  65. package/dist/{weather-report-UYKQUSBB.js → weather-report-OHHDUNX3.js} +2 -2
  66. package/package.json +1 -1
  67. package/dist/chunk-3PQIIMHN.js.map +0 -1
  68. package/dist/issue-triage-BIEZBWV2.js +0 -16
  69. package/dist/setup-data-dir-UNM34FGW.js +0 -32
  70. /package/dist/{ast-rule-runner-AMZCLKRV.js.map → ast-rule-runner-NOWNF5QY.js.map} +0 -0
  71. /package/dist/{child-mcp-config-7DSYI325.js.map → child-mcp-config-UBKF4SOL.js.map} +0 -0
  72. /package/dist/{chunk-XU2SJKFK.js.map → chunk-2C5ABWLK.js.map} +0 -0
  73. /package/dist/{chunk-SCXCJSTT.js.map → chunk-3E4BZR3V.js.map} +0 -0
  74. /package/dist/{chunk-BJXSG5YL.js.map → chunk-4W4S6OBP.js.map} +0 -0
  75. /package/dist/{chunk-Z5VUMKF5.js.map → chunk-5JZ635RM.js.map} +0 -0
  76. /package/dist/{chunk-ZTTBGME2.js.map → chunk-5XCRXV43.js.map} +0 -0
  77. /package/dist/{chunk-KQE7EFBF.js.map → chunk-6YQ55DOE.js.map} +0 -0
  78. /package/dist/{chunk-AXBEG6VW.js.map → chunk-6ZPHMRJQ.js.map} +0 -0
  79. /package/dist/{chunk-CG7OSI5P.js.map → chunk-F3PIVN3B.js.map} +0 -0
  80. /package/dist/{chunk-5GZ4UN5F.js.map → chunk-GLG667IV.js.map} +0 -0
  81. /package/dist/{chunk-UDWZJY3V.js.map → chunk-GPEGBNGB.js.map} +0 -0
  82. /package/dist/{chunk-JYKRCQSU.js.map → chunk-H7PL2D5A.js.map} +0 -0
  83. /package/dist/{chunk-GYQIIAVM.js.map → chunk-K6IVHUEK.js.map} +0 -0
  84. /package/dist/{chunk-5XZCL7QT.js.map → chunk-LBYA22G5.js.map} +0 -0
  85. /package/dist/{chunk-3IBALX36.js.map → chunk-LVL6WCWK.js.map} +0 -0
  86. /package/dist/{chunk-E6AJH4F4.js.map → chunk-NBVYSGSS.js.map} +0 -0
  87. /package/dist/{chunk-GXBXZCY7.js.map → chunk-NRSAOTT7.js.map} +0 -0
  88. /package/dist/{chunk-NZN3SWSZ.js.map → chunk-P2RI4DGX.js.map} +0 -0
  89. /package/dist/{chunk-JYZNPK62.js.map → chunk-P5ND7MWI.js.map} +0 -0
  90. /package/dist/{chunk-TRCYUQ4M.js.map → chunk-PEN5XFMP.js.map} +0 -0
  91. /package/dist/{chunk-XJAGCUMD.js.map → chunk-R57JPKHJ.js.map} +0 -0
  92. /package/dist/{chunk-4IV25ZUM.js.map → chunk-RQBI56JN.js.map} +0 -0
  93. /package/dist/{chunk-6FFBX665.js.map → chunk-SFHIXQGK.js.map} +0 -0
  94. /package/dist/{chunk-5UCGVAEZ.js.map → chunk-SXS2YQUK.js.map} +0 -0
  95. /package/dist/{chunk-VM4HZT3B.js.map → chunk-TFZDHQ45.js.map} +0 -0
  96. /package/dist/{chunk-JRZEB4OQ.js.map → chunk-U2C6V65K.js.map} +0 -0
  97. /package/dist/{chunk-LZNYQYDU.js.map → chunk-UR2KFP6P.js.map} +0 -0
  98. /package/dist/{chunk-EKZ6V7SE.js.map → chunk-XM2GVJPE.js.map} +0 -0
  99. /package/dist/{chunk-HLXXP3CS.js.map → chunk-XS3IJG4V.js.map} +0 -0
  100. /package/dist/{chunk-ILA4UGXI.js.map → chunk-YBW45NIZ.js.map} +0 -0
  101. /package/dist/{chunk-PENEGF75.js.map → chunk-YG3UYPKL.js.map} +0 -0
  102. /package/dist/{chunk-LFFXUHX3.js.map → chunk-YT7EP2B6.js.map} +0 -0
  103. /package/dist/{chunk-TLFZPJOY.js.map → chunk-YYVBEHM3.js.map} +0 -0
  104. /package/dist/{cli-circuit-breaker-MCQG3PQK.js.map → cli-circuit-breaker-IFVKXCHQ.js.map} +0 -0
  105. /package/dist/{composite-router-QAYCHEFG.js.map → composite-router-7LFS4CMF.js.map} +0 -0
  106. /package/dist/{consensus-vote-UHNEKOO7.js.map → consensus-vote-SA2KVDQA.js.map} +0 -0
  107. /package/dist/{context-retriever-UXQCDDRY.js.map → context-retriever-V7OWZW7R.js.map} +0 -0
  108. /package/dist/{doctor-deep-QRLRDFM4.js.map → doctor-deep-GJPTXS2N.js.map} +0 -0
  109. /package/dist/{doctor-live-CUKBQSSH.js.map → doctor-live-ET5O7O2D.js.map} +0 -0
  110. /package/dist/{expert-bridge-ZG2IA3RJ.js.map → expert-bridge-G656VGZG.js.map} +0 -0
  111. /package/dist/{factory-FPNYFKXU.js.map → factory-BQBFECEV.js.map} +0 -0
  112. /package/dist/{factory-RQEHJ4AW.js.map → factory-N34PTEMW.js.map} +0 -0
  113. /package/dist/{improvement-review-N36SVUDG.js.map → improvement-review-YIXDCEX4.js.map} +0 -0
  114. /package/dist/{init-opencode-4QECASK4.js.map → init-opencode-33EU3PD6.js.map} +0 -0
  115. /package/dist/{issue-triage-BIEZBWV2.js.map → issue-triage-URFEVDIX.js.map} +0 -0
  116. /package/dist/{pr-reviewer-helpers-RK5IT4US.js.map → pr-reviewer-helpers-ZDAJARQ7.js.map} +0 -0
  117. /package/dist/{registry-command-MBZFFDWS.js.map → registry-command-AB7KP7DK.js.map} +0 -0
  118. /package/dist/{repo-security-plan-W76YLC2M.js.map → repo-security-plan-YV3ZFKGO.js.map} +0 -0
  119. /package/dist/{research-helpers-synthesize-GI5JFAQM.js.map → research-helpers-synthesize-EOHUBGH3.js.map} +0 -0
  120. /package/dist/{routing-memory-WLCUOPDE.js.map → routing-memory-34JWGSAI.js.map} +0 -0
  121. /package/dist/{session-memory-HU3XMQEH.js.map → session-memory-QGIJCM7P.js.map} +0 -0
  122. /package/dist/{setup-config-XA756R2O.js.map → setup-config-3KBMBPCN.js.map} +0 -0
  123. /package/dist/{setup-custom-api-ETBGOE7O.js.map → setup-custom-api-652FK232.js.map} +0 -0
  124. /package/dist/{setup-data-dir-UNM34FGW.js.map → setup-data-dir-XJMN4ALO.js.map} +0 -0
  125. /package/dist/{tool-memory-7XMQAQQM.js.map → tool-memory-SPPCBLKQ.js.map} +0 -0
  126. /package/dist/{unified-registry-LR4OCUFI.js.map → unified-registry-ZOLSOVYN.js.map} +0 -0
  127. /package/dist/{weather-report-UYKQUSBB.js.map → weather-report-OHHDUNX3.js.map} +0 -0
@@ -9,8 +9,8 @@ import {
9
9
  getBuiltInAstRulesPath,
10
10
  loadRules,
11
11
  runAstQaRules
12
- } from "./chunk-LFFXUHX3.js";
13
- import "./chunk-NZN3SWSZ.js";
12
+ } from "./chunk-YT7EP2B6.js";
13
+ import "./chunk-P2RI4DGX.js";
14
14
  import "./chunk-UE7A2XHM.js";
15
15
  import "./chunk-LWOX65CP.js";
16
16
  import "./chunk-PX6F3LHL.js";
@@ -26,4 +26,4 @@ export {
26
26
  loadRules,
27
27
  runAstQaRules
28
28
  };
29
- //# sourceMappingURL=ast-rule-runner-AMZCLKRV.js.map
29
+ //# sourceMappingURL=ast-rule-runner-NOWNF5QY.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-OITVVSWO.js";
4
4
  import {
5
5
  createLogger
6
- } from "./chunk-NZN3SWSZ.js";
6
+ } from "./chunk-P2RI4DGX.js";
7
7
  import "./chunk-UE7A2XHM.js";
8
8
  import "./chunk-LWOX65CP.js";
9
9
  import "./chunk-PX6F3LHL.js";
@@ -56,4 +56,4 @@ async function generateMcpConfig(options) {
56
56
  export {
57
57
  generateMcpConfig
58
58
  };
59
- //# sourceMappingURL=child-mcp-config-7DSYI325.js.map
59
+ //# sourceMappingURL=child-mcp-config-UBKF4SOL.js.map
@@ -10,7 +10,7 @@ import {
10
10
  isRateLimitText,
11
11
  observedArmDisplaySlot,
12
12
  ok
13
- } from "./chunk-NZN3SWSZ.js";
13
+ } from "./chunk-P2RI4DGX.js";
14
14
 
15
15
  // src/cli-adapters/circuit-breaker-types.ts
16
16
  var CircuitErrorCode = {
@@ -592,4 +592,4 @@ export {
592
592
  CliCircuitBreakerIntegration,
593
593
  createCliCircuitBreakerIntegration
594
594
  };
595
- //# sourceMappingURL=chunk-XU2SJKFK.js.map
595
+ //# sourceMappingURL=chunk-2C5ABWLK.js.map
@@ -4,7 +4,7 @@ import {
4
4
  err,
5
5
  getErrorMessage,
6
6
  ok
7
- } from "./chunk-NZN3SWSZ.js";
7
+ } from "./chunk-P2RI4DGX.js";
8
8
 
9
9
  // src/scm/types.ts
10
10
  var ScmError = class extends Error {
@@ -281,4 +281,4 @@ export {
281
281
  ScmError,
282
282
  GitHubProvider
283
283
  };
284
- //# sourceMappingURL=chunk-SCXCJSTT.js.map
284
+ //# sourceMappingURL=chunk-3E4BZR3V.js.map
@@ -4,12 +4,12 @@ import {
4
4
  planOptionalParams,
5
5
  requireApiKey,
6
6
  validateApiKeyPresence
7
- } from "./chunk-ZTTBGME2.js";
7
+ } from "./chunk-5XCRXV43.js";
8
8
  import {
9
9
  assertCustomApiHostResolvesPublic,
10
10
  hostnameOf,
11
11
  redactApiKey
12
- } from "./chunk-LZNYQYDU.js";
12
+ } from "./chunk-UR2KFP6P.js";
13
13
  import {
14
14
  sanitizeErrorDetails
15
15
  } from "./chunk-2NDA4DHW.js";
@@ -31,7 +31,7 @@ import {
31
31
  isEndpointArmId,
32
32
  ok,
33
33
  recordUsageEvent
34
- } from "./chunk-NZN3SWSZ.js";
34
+ } from "./chunk-P2RI4DGX.js";
35
35
 
36
36
  // src/adapters/openai-types.ts
37
37
  var OPENAI_MODELS = {
@@ -886,4 +886,4 @@ export {
886
886
  discoverModels,
887
887
  buildOpenAICompatAdapters
888
888
  };
889
- //# sourceMappingURL=chunk-BJXSG5YL.js.map
889
+ //# sourceMappingURL=chunk-4W4S6OBP.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  loadPapersRegistry
3
- } from "./chunk-CG7OSI5P.js";
3
+ } from "./chunk-F3PIVN3B.js";
4
4
  import {
5
5
  getErrorMessage
6
- } from "./chunk-NZN3SWSZ.js";
6
+ } from "./chunk-P2RI4DGX.js";
7
7
 
8
8
  // src/cli/research-helpers-synthesize.ts
9
9
  import { z } from "zod";
@@ -876,4 +876,4 @@ export {
876
876
  AttributedInsightSchema,
877
877
  synthesizeResearch
878
878
  };
879
- //# sourceMappingURL=chunk-Z5VUMKF5.js.map
879
+ //# sourceMappingURL=chunk-5JZ635RM.js.map
@@ -13,7 +13,7 @@ import {
13
13
  lookupInTreeCapability,
14
14
  ok,
15
15
  resolveRetryAfterMs
16
- } from "./chunk-NZN3SWSZ.js";
16
+ } from "./chunk-P2RI4DGX.js";
17
17
 
18
18
  // src/config/model-parameter-support.ts
19
19
  function parseClaudeMajorMinor(bareId) {
@@ -834,4 +834,4 @@ export {
834
834
  DEFAULT_COLLECT_STREAM_MAX_CHUNKS,
835
835
  collectStream
836
836
  };
837
- //# sourceMappingURL=chunk-ZTTBGME2.js.map
837
+ //# sourceMappingURL=chunk-5XCRXV43.js.map
@@ -8,13 +8,13 @@ import {
8
8
  loadTechniquesRegistry,
9
9
  resolveInsideRoot,
10
10
  savePapersRegistry
11
- } from "./chunk-CG7OSI5P.js";
11
+ } from "./chunk-F3PIVN3B.js";
12
12
  import {
13
13
  resolveToken
14
- } from "./chunk-UDWZJY3V.js";
14
+ } from "./chunk-GPEGBNGB.js";
15
15
  import {
16
16
  getToolMemory
17
- } from "./chunk-VM4HZT3B.js";
17
+ } from "./chunk-TFZDHQ45.js";
18
18
  import {
19
19
  capitalizeWords,
20
20
  tokenizeFiltered,
@@ -43,7 +43,7 @@ import {
43
43
  ok,
44
44
  registerPersistentDistillerFactory,
45
45
  sigmoidConfidence
46
- } from "./chunk-NZN3SWSZ.js";
46
+ } from "./chunk-P2RI4DGX.js";
47
47
  import {
48
48
  ensureLearningDir,
49
49
  getRulesFile
@@ -4275,4 +4275,4 @@ export {
4275
4275
  DEFAULT_CONTEXT_BUDGET_TOKENS,
4276
4276
  getContextPromptPrefix
4277
4277
  };
4278
- //# sourceMappingURL=chunk-KQE7EFBF.js.map
4278
+ //# sourceMappingURL=chunk-6YQ55DOE.js.map
@@ -6,17 +6,17 @@ import {
6
6
  } from "./chunk-3KDQKVCJ.js";
7
7
  import {
8
8
  allOf
9
- } from "./chunk-OQB3XC5O.js";
9
+ } from "./chunk-EZNIYU5T.js";
10
10
  import {
11
11
  assessReputation,
12
12
  sanitizeInput
13
- } from "./chunk-5GZ4UN5F.js";
13
+ } from "./chunk-GLG667IV.js";
14
14
  import {
15
15
  createLogger,
16
16
  err,
17
17
  getTimeProvider,
18
18
  ok
19
- } from "./chunk-NZN3SWSZ.js";
19
+ } from "./chunk-P2RI4DGX.js";
20
20
 
21
21
  // src/dogfooding/pr-reviewer-helpers.ts
22
22
  import { randomUUID } from "node:crypto";
@@ -416,4 +416,4 @@ export {
416
416
  createFailedReview,
417
417
  reviewPostingBlock
418
418
  };
419
- //# sourceMappingURL=chunk-AXBEG6VW.js.map
419
+ //# sourceMappingURL=chunk-6ZPHMRJQ.js.map
@@ -1,12 +1,18 @@
1
1
  import {
2
+ allOf,
3
+ verdictOver
4
+ } from "./chunk-EZNIYU5T.js";
5
+ import {
6
+ ApiArmIdSchema,
2
7
  TASK_CATEGORIES,
3
8
  getAdaptiveBonus,
4
9
  getOutcomeStore
5
- } from "./chunk-NZN3SWSZ.js";
10
+ } from "./chunk-P2RI4DGX.js";
6
11
 
7
12
  // src/cli/doctor-deep.ts
8
13
  var CLI_NAMES = ["claude", "gemini", "codex", "opencode"];
9
14
  var COLD_START_THRESHOLD = 3;
15
+ var ROUTED_ARMS = [...CLI_NAMES, ...ApiArmIdSchema.options];
10
16
  function checkLearningLoop() {
11
17
  const store = getOutcomeStore();
12
18
  const outcomes = store.query();
@@ -44,29 +50,45 @@ function checkDataSufficiency() {
44
50
  const missing = TASK_CATEGORIES.filter((c) => !categoriesWithData.has(c));
45
51
  return { cliStatus, missingCategories: missing, coldStartThreshold: COLD_START_THRESHOLD };
46
52
  }
53
+ function roundRate(rate) {
54
+ return Math.round(rate * 1e3) / 1e3;
55
+ }
56
+ function tallyRowsByArm() {
57
+ const byArm = /* @__PURE__ */ new Map();
58
+ for (const o of getOutcomeStore().query()) {
59
+ if (!ROUTED_ARMS.includes(o.cli)) continue;
60
+ const tally = byArm.get(o.cli) ?? { total: 0, successes: 0 };
61
+ tally.total++;
62
+ if (o.success) tally.successes++;
63
+ byArm.set(o.cli, tally);
64
+ }
65
+ return byArm;
66
+ }
47
67
  function checkConvergence() {
48
- const store = getOutcomeStore();
68
+ const rowsByArm = tallyRowsByArm();
69
+ const measured = [];
49
70
  const rates = /* @__PURE__ */ new Map();
50
- let totalRate = 0;
51
- for (const cli of CLI_NAMES) {
52
- const outcomes = store.query({ cli });
53
- if (outcomes.length > 0) {
54
- const rate = outcomes.filter((o) => o.success).length / outcomes.length;
55
- rates.set(cli, Math.round(rate * 1e3) / 1e3);
56
- totalRate += rate;
57
- } else {
58
- rates.set(cli, 0);
71
+ for (const arm of ROUTED_ARMS) {
72
+ const tally = rowsByArm.get(arm);
73
+ if (tally === void 0) {
74
+ rates.set(arm, { status: "unmeasured" });
75
+ continue;
59
76
  }
77
+ const rate = tally.successes / tally.total;
78
+ measured.push({ rate, sampleCount: tally.total });
79
+ rates.set(arm, { status: "measured", rate: roundRate(rate), sampleCount: tally.total });
60
80
  }
61
- const avgRate = totalRate / CLI_NAMES.length;
62
- const allAboveThreshold = CLI_NAMES.every((cli) => {
63
- const outcomes = store.query({ cli });
64
- return outcomes.length >= COLD_START_THRESHOLD;
65
- });
81
+ const avgSuccessRate = verdictOver(
82
+ measured,
83
+ (arms) => roundRate(arms.reduce((sum, a) => sum + a.rate, 0) / arms.length),
84
+ "unmeasured"
85
+ );
86
+ const converged = allOf(measured, (a) => a.sampleCount >= COLD_START_THRESHOLD, false);
66
87
  return {
67
- avgSuccessRate: Math.round(avgRate * 1e3) / 1e3,
68
- cliSuccessRates: rates,
69
- converged: allAboveThreshold
88
+ avgSuccessRate,
89
+ armSuccessRates: rates,
90
+ measuredArmCount: measured.length,
91
+ converged
70
92
  };
71
93
  }
72
94
  function runDeepDiagnostics() {
@@ -76,6 +98,23 @@ function runDeepDiagnostics() {
76
98
  routingConvergence: checkConvergence()
77
99
  };
78
100
  }
101
+ function formatConvergenceRates(rc) {
102
+ const pct = (rate) => `${(rate * 100).toFixed(1)}%`;
103
+ if (rc.avgSuccessRate === "unmeasured") {
104
+ return [" Avg success rate: unmeasured (no arm has outcome rows)"];
105
+ }
106
+ const noun = rc.measuredArmCount === 1 ? "arm" : "arms";
107
+ const lines = [
108
+ ` Avg success rate: ${pct(rc.avgSuccessRate)} over ${String(rc.measuredArmCount)} measured ${noun}`
109
+ ];
110
+ const unmeasured = [];
111
+ for (const [arm, r] of rc.armSuccessRates) {
112
+ if (r.status === "unmeasured") unmeasured.push(arm);
113
+ else lines.push(` ${arm}: ${pct(r.rate)} (${String(r.sampleCount)} runs)`);
114
+ }
115
+ if (unmeasured.length > 0) lines.push(` Unmeasured (no rows): ${unmeasured.join(", ")}`);
116
+ return lines;
117
+ }
79
118
  function formatDeepDiagnostics(diag) {
80
119
  const lines = ["\n=== Deep Diagnostics ===\n"];
81
120
  const ll = diag.learningLoop;
@@ -97,7 +136,7 @@ function formatDeepDiagnostics(diag) {
97
136
  }
98
137
  const rc = diag.routingConvergence;
99
138
  lines.push("\nRouting Convergence:");
100
- lines.push(` Avg success rate: ${(rc.avgSuccessRate * 100).toFixed(1)}%`);
139
+ lines.push(...formatConvergenceRates(rc));
101
140
  lines.push(` Converged: ${rc.converged ? "yes" : "no (still below cold-start threshold)"}`);
102
141
  return lines.join("\n");
103
142
  }
@@ -106,4 +145,4 @@ export {
106
145
  runDeepDiagnostics,
107
146
  formatDeepDiagnostics
108
147
  };
109
- //# sourceMappingURL=chunk-3PQIIMHN.js.map
148
+ //# sourceMappingURL=chunk-DGW6C2PT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/doctor-deep.ts"],"sourcesContent":["/**\n * Deep diagnostics for the doctor command.\n *\n * Surfaces learning loop health, data sufficiency, routing convergence,\n * and memory system status. Opt-in via `--deep` flag.\n *\n * @module cli/doctor-deep\n * (Source: Issue #1031 — Enhanced doctor --deep diagnostics)\n */\n\nimport { getOutcomeStore } from '../orchestration/outcomes/outcome-store.js';\nimport { TASK_CATEGORIES, type TaskCategory } from '../config/task-specialization-types.js';\nimport { getAdaptiveBonus } from '../mcp/tools/weather-report.js';\nimport { ApiArmIdSchema } from '../cli-adapters/types-core.js';\nimport { allOf, verdictOver } from '../utils/verdict-aggregation.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Per-CLI data sufficiency snapshot. */\nexport interface CliDataStatus {\n readonly cli: string;\n readonly taskCount: number;\n readonly aboveThreshold: boolean;\n}\n\n/** Deep diagnostics result. */\nexport interface DeepDiagnostics {\n readonly learningLoop: LearningLoopHealth;\n readonly dataSufficiency: DataSufficiency;\n readonly routingConvergence: RoutingConvergence;\n}\n\nexport interface LearningLoopHealth {\n readonly totalOutcomes: number;\n readonly latestTimestamp: string | null;\n readonly activeBonuses: number;\n readonly totalBonusPairs: number;\n}\n\nexport interface DataSufficiency {\n readonly cliStatus: readonly CliDataStatus[];\n readonly missingCategories: readonly string[];\n readonly coldStartThreshold: number;\n}\n\n/**\n * One arm's success rate. An arm with no outcome rows is `unmeasured` — not a\n * 0% rate, which would claim every attempt failed (#6557).\n */\nexport type ArmSuccessRate =\n | { readonly status: 'measured'; readonly rate: number; readonly sampleCount: number }\n | { readonly status: 'unmeasured' };\n\nexport interface RoutingConvergence {\n /**\n * Mean success rate over MEASURED arms only. `'unmeasured'` when no arm has\n * a row — the empty case, which is neither 0 nor NaN (#6557).\n */\n readonly avgSuccessRate: number | 'unmeasured';\n /** Every routed arm (CLI slots and `api:*` arms), measured or not. */\n readonly armSuccessRates: ReadonlyMap<string, ArmSuccessRate>;\n /** Number of arms with at least one outcome row: the average's divisor. */\n readonly measuredArmCount: number;\n /** Every measured arm has cleared the cold-start threshold; false when none is measured. */\n readonly converged: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst CLI_NAMES = ['claude', 'gemini', 'codex', 'opencode'] as const;\nconst COLD_START_THRESHOLD = 3;\n\n/**\n * CLI slots plus API arms: every `cli` an attributed outcome row can carry.\n * Routed rows record the arm that ran (`api:anthropic`), not its slot, since\n * #6554. `unknown` is deliberately absent: an unattributed row is no arm's\n * measurement.\n */\nconst ROUTED_ARMS: readonly string[] = [...CLI_NAMES, ...ApiArmIdSchema.options];\n\n// ============================================================================\n// Diagnostics\n// ============================================================================\n\n/** Check learning loop health: outcome count, latest timestamp, bonuses. */\nfunction checkLearningLoop(): LearningLoopHealth {\n const store = getOutcomeStore();\n const outcomes = store.query();\n const latestTimestamp =\n outcomes.length > 0 ? (outcomes[outcomes.length - 1]?.timestamp ?? null) : null;\n\n let activeBonuses = 0;\n const totalPairs = CLI_NAMES.length * TASK_CATEGORIES.length;\n for (const cli of CLI_NAMES) {\n for (const cat of TASK_CATEGORIES) {\n if (getAdaptiveBonus(cli, cat) !== 0) activeBonuses++;\n }\n }\n\n return {\n totalOutcomes: outcomes.length,\n latestTimestamp,\n activeBonuses,\n totalBonusPairs: totalPairs,\n };\n}\n\n/** Check per-CLI data sufficiency against cold-start threshold. */\nfunction checkDataSufficiency(): DataSufficiency {\n const store = getOutcomeStore();\n const cliStatus: CliDataStatus[] = [];\n\n for (const cli of CLI_NAMES) {\n const outcomes = store.query({ cli });\n cliStatus.push({\n cli,\n taskCount: outcomes.length,\n aboveThreshold: outcomes.length >= COLD_START_THRESHOLD,\n });\n }\n\n const categoriesWithData = new Set<TaskCategory>();\n const allOutcomes = store.query();\n for (const o of allOutcomes) {\n categoriesWithData.add(o.category);\n }\n const missing = TASK_CATEGORIES.filter((c) => !categoriesWithData.has(c));\n\n return { cliStatus, missingCategories: missing, coldStartThreshold: COLD_START_THRESHOLD };\n}\n\n/** Round a rate to three decimals for display-stable output. */\nfunction roundRate(rate: number): number {\n return Math.round(rate * 1000) / 1000;\n}\n\ninterface MeasuredArm {\n readonly rate: number;\n readonly sampleCount: number;\n}\n\n/** Tally rows per routed arm; rows carrying no routed arm (`unknown`) are skipped. */\nfunction tallyRowsByArm(): Map<string, { total: number; successes: number }> {\n const byArm = new Map<string, { total: number; successes: number }>();\n for (const o of getOutcomeStore().query()) {\n if (!ROUTED_ARMS.includes(o.cli)) continue;\n const tally = byArm.get(o.cli) ?? { total: 0, successes: 0 };\n tally.total++;\n if (o.success) tally.successes++;\n byArm.set(o.cli, tally);\n }\n return byArm;\n}\n\n/**\n * Check routing convergence from outcome success rates (#6557).\n *\n * Covers the arms rows actually carry, CLI and `api:*` alike. An arm with no\n * rows is `unmeasured` and stays out of the average, whose divisor is the\n * number of measured arms, never a fixed list.\n */\nfunction checkConvergence(): RoutingConvergence {\n const rowsByArm = tallyRowsByArm();\n const measured: MeasuredArm[] = [];\n const rates = new Map<string, ArmSuccessRate>();\n for (const arm of ROUTED_ARMS) {\n const tally = rowsByArm.get(arm);\n if (tally === undefined) {\n rates.set(arm, { status: 'unmeasured' });\n continue;\n }\n const rate = tally.successes / tally.total;\n measured.push({ rate, sampleCount: tally.total });\n rates.set(arm, { status: 'measured', rate: roundRate(rate), sampleCount: tally.total });\n }\n\n // Empty case named: with no measured arm there is no rate to average.\n const avgSuccessRate = verdictOver<MeasuredArm, number | 'unmeasured'>(\n measured,\n (arms) => roundRate(arms.reduce((sum, a) => sum + a.rate, 0) / arms.length),\n 'unmeasured'\n );\n // Nothing measured has not converged on anything.\n const converged = allOf(measured, (a) => a.sampleCount >= COLD_START_THRESHOLD, false);\n\n return {\n avgSuccessRate,\n armSuccessRates: rates,\n measuredArmCount: measured.length,\n converged,\n };\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/** Run all deep diagnostics. */\nexport function runDeepDiagnostics(): DeepDiagnostics {\n return {\n learningLoop: checkLearningLoop(),\n dataSufficiency: checkDataSufficiency(),\n routingConvergence: checkConvergence(),\n };\n}\n\n/** Render convergence rates, naming unmeasured arms rather than showing them as 0%. */\nfunction formatConvergenceRates(rc: RoutingConvergence): string[] {\n const pct = (rate: number): string => `${(rate * 100).toFixed(1)}%`;\n if (rc.avgSuccessRate === 'unmeasured') {\n return [' Avg success rate: unmeasured (no arm has outcome rows)'];\n }\n const noun = rc.measuredArmCount === 1 ? 'arm' : 'arms';\n const lines = [\n ` Avg success rate: ${pct(rc.avgSuccessRate)} over ${String(rc.measuredArmCount)} measured ${noun}`,\n ];\n const unmeasured: string[] = [];\n for (const [arm, r] of rc.armSuccessRates) {\n if (r.status === 'unmeasured') unmeasured.push(arm);\n else lines.push(` ${arm}: ${pct(r.rate)} (${String(r.sampleCount)} runs)`);\n }\n if (unmeasured.length > 0) lines.push(` Unmeasured (no rows): ${unmeasured.join(', ')}`);\n return lines;\n}\n\n/** Format deep diagnostics for CLI output. */\nexport function formatDeepDiagnostics(diag: DeepDiagnostics): string {\n const lines: string[] = ['\\n=== Deep Diagnostics ===\\n'];\n\n // Learning Loop\n const ll = diag.learningLoop;\n lines.push('Learning Loop:');\n const outcomeIcon = ll.totalOutcomes > 0 ? '+' : '-';\n lines.push(` ${outcomeIcon} OutcomeStore: ${String(ll.totalOutcomes)} entries`);\n const bonusIcon = ll.activeBonuses > 0 ? '+' : '-';\n lines.push(\n ` ${bonusIcon} Adaptive bonuses: ${String(ll.activeBonuses)}/${String(ll.totalBonusPairs)} active`\n );\n\n // Data Sufficiency\n lines.push('\\nData Sufficiency:');\n for (const cs of diag.dataSufficiency.cliStatus) {\n const icon = cs.aboveThreshold ? '+' : '!';\n const label = cs.aboveThreshold ? 'above threshold' : 'below threshold';\n lines.push(` ${icon} ${cs.cli}: ${String(cs.taskCount)} tasks (${label})`);\n }\n if (diag.dataSufficiency.missingCategories.length > 0) {\n lines.push(` Missing categories: ${diag.dataSufficiency.missingCategories.join(', ')}`);\n }\n\n // Routing Convergence\n const rc = diag.routingConvergence;\n lines.push('\\nRouting Convergence:');\n lines.push(...formatConvergenceRates(rc));\n lines.push(` Converged: ${rc.converged ? 'yes' : 'no (still below cold-start threshold)'}`);\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":[]}
@@ -7,9 +7,14 @@ function anyOf(items, predicate, whenEmpty) {
7
7
  if (items.length === 0) return whenEmpty;
8
8
  return items.some(predicate);
9
9
  }
10
+ function verdictOver(items, aggregate, whenEmpty) {
11
+ if (items.length === 0) return whenEmpty;
12
+ return aggregate(items);
13
+ }
10
14
 
11
15
  export {
12
16
  allOf,
13
- anyOf
17
+ anyOf,
18
+ verdictOver
14
19
  };
15
- //# sourceMappingURL=chunk-OQB3XC5O.js.map
20
+ //# sourceMappingURL=chunk-EZNIYU5T.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/verdict-aggregation.ts"],"sourcesContent":["/**\n * Aggregating a verdict over a collection that might be empty (#4580).\n *\n * `[].every(p)` is `true` in JavaScript. So `checks.every((c) => c.passed)`\n * reports **pass** when `checks` is empty — absence rendered as health, on\n * exactly the code paths where that is most dangerous.\n *\n * Confirmed instances of the shape:\n * - `verify_audit_chain` returns `ok: true` over zero events, so deleting\n * every audit log file makes a tamper-evident chain verify clean (#4579)\n * - a quality gate with zero checks reported `pass` (#4544)\n * - the QA pipeline stage reported `success` after reviewing zero tasks,\n * letting the graph advance as though implementations had been reviewed\n *\n * ## Why a helper rather than a lint or a type\n *\n * Measured before choosing: 64 non-test `.every()` calls, and most are fine —\n * `github-provider.ts:178` guards with `length > 0` and correctly leaves an\n * empty check set `pending`. A wide surface with sparse defects, so a blanket\n * lint would be mostly false positives, and false positives are what teach\n * people to bypass a gate.\n *\n * What was missing is not enforcement but a *decision point*: nothing made the\n * author say what empty means. `whenEmpty` is a required argument, so they\n * must. Chosen by a 7-voter `higher_order` panel at the supermajority bar.\n *\n * ## Choosing `whenEmpty`\n *\n * Ask what an empty collection is evidence OF. Usually nothing — in which case\n * the honest answer is the non-committal verdict (`pending`, `unmeasured`,\n * `skip`), not the optimistic one. Reserve `true` for cases where vacuous truth\n * is genuinely the contract, and say so at the call site.\n *\n * @module utils/verdict-aggregation\n * (Source: Issue #4580)\n */\n\n/**\n * `predicate` holds for every item — with the empty case named, not defaulted.\n *\n * @param items - The collection to judge.\n * @param predicate - Must hold for each item.\n * @param whenEmpty - The verdict when there is nothing to judge. Required.\n */\nexport function allOf<T>(\n items: readonly T[],\n predicate: (item: T) => boolean,\n whenEmpty: boolean\n): boolean {\n if (items.length === 0) return whenEmpty;\n return items.every(predicate);\n}\n\n/**\n * `predicate` holds for at least one item — with the empty case named.\n *\n * `[].some(p)` is already `false`, which is usually right, but not always: a\n * \"did anything fail?\" check over zero results should often be `unmeasured`\n * rather than a clean `false`. Naming it keeps the reasoning visible.\n *\n * @param items - The collection to judge.\n * @param predicate - Must hold for at least one item.\n * @param whenEmpty - The verdict when there is nothing to judge. Required.\n */\nexport function anyOf<T>(\n items: readonly T[],\n predicate: (item: T) => boolean,\n whenEmpty: boolean\n): boolean {\n if (items.length === 0) return whenEmpty;\n return items.some(predicate);\n}\n\n/**\n * Reduce a collection to an arbitrary verdict, with the empty case named.\n *\n * For verdicts richer than a boolean — a severity, a tri-state gate result —\n * where the empty case is usually `unmeasured` rather than the best value.\n *\n * @param items - The collection to judge.\n * @param aggregate - Folds a non-empty collection into a verdict.\n * @param whenEmpty - The verdict when there is nothing to judge. Required.\n */\nexport function verdictOver<T, V>(\n items: readonly T[],\n aggregate: (items: readonly T[]) => V,\n whenEmpty: V\n): V {\n if (items.length === 0) return whenEmpty;\n return aggregate(items);\n}\n"],"mappings":";AA4CO,SAAS,MACd,OACA,WACA,WACS;AACT,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,MAAM,SAAS;AAC9B;AAaO,SAAS,MACd,OACA,WACA,WACS;AACT,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,KAAK,SAAS;AAC7B;","names":[]}
1
+ {"version":3,"sources":["../src/utils/verdict-aggregation.ts"],"sourcesContent":["/**\n * Aggregating a verdict over a collection that might be empty (#4580).\n *\n * `[].every(p)` is `true` in JavaScript. So `checks.every((c) => c.passed)`\n * reports **pass** when `checks` is empty — absence rendered as health, on\n * exactly the code paths where that is most dangerous.\n *\n * Confirmed instances of the shape:\n * - `verify_audit_chain` returns `ok: true` over zero events, so deleting\n * every audit log file makes a tamper-evident chain verify clean (#4579)\n * - a quality gate with zero checks reported `pass` (#4544)\n * - the QA pipeline stage reported `success` after reviewing zero tasks,\n * letting the graph advance as though implementations had been reviewed\n *\n * ## Why a helper rather than a lint or a type\n *\n * Measured before choosing: 64 non-test `.every()` calls, and most are fine —\n * `github-provider.ts:178` guards with `length > 0` and correctly leaves an\n * empty check set `pending`. A wide surface with sparse defects, so a blanket\n * lint would be mostly false positives, and false positives are what teach\n * people to bypass a gate.\n *\n * What was missing is not enforcement but a *decision point*: nothing made the\n * author say what empty means. `whenEmpty` is a required argument, so they\n * must. Chosen by a 7-voter `higher_order` panel at the supermajority bar.\n *\n * ## Choosing `whenEmpty`\n *\n * Ask what an empty collection is evidence OF. Usually nothing — in which case\n * the honest answer is the non-committal verdict (`pending`, `unmeasured`,\n * `skip`), not the optimistic one. Reserve `true` for cases where vacuous truth\n * is genuinely the contract, and say so at the call site.\n *\n * @module utils/verdict-aggregation\n * (Source: Issue #4580)\n */\n\n/**\n * `predicate` holds for every item — with the empty case named, not defaulted.\n *\n * @param items - The collection to judge.\n * @param predicate - Must hold for each item.\n * @param whenEmpty - The verdict when there is nothing to judge. Required.\n */\nexport function allOf<T>(\n items: readonly T[],\n predicate: (item: T) => boolean,\n whenEmpty: boolean\n): boolean {\n if (items.length === 0) return whenEmpty;\n return items.every(predicate);\n}\n\n/**\n * `predicate` holds for at least one item — with the empty case named.\n *\n * `[].some(p)` is already `false`, which is usually right, but not always: a\n * \"did anything fail?\" check over zero results should often be `unmeasured`\n * rather than a clean `false`. Naming it keeps the reasoning visible.\n *\n * @param items - The collection to judge.\n * @param predicate - Must hold for at least one item.\n * @param whenEmpty - The verdict when there is nothing to judge. Required.\n */\nexport function anyOf<T>(\n items: readonly T[],\n predicate: (item: T) => boolean,\n whenEmpty: boolean\n): boolean {\n if (items.length === 0) return whenEmpty;\n return items.some(predicate);\n}\n\n/**\n * Reduce a collection to an arbitrary verdict, with the empty case named.\n *\n * For verdicts richer than a boolean — a severity, a tri-state gate result —\n * where the empty case is usually `unmeasured` rather than the best value.\n *\n * @param items - The collection to judge.\n * @param aggregate - Folds a non-empty collection into a verdict.\n * @param whenEmpty - The verdict when there is nothing to judge. Required.\n */\nexport function verdictOver<T, V>(\n items: readonly T[],\n aggregate: (items: readonly T[]) => V,\n whenEmpty: V\n): V {\n if (items.length === 0) return whenEmpty;\n return aggregate(items);\n}\n"],"mappings":";AA4CO,SAAS,MACd,OACA,WACA,WACS;AACT,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,MAAM,SAAS;AAC9B;AAaO,SAAS,MACd,OACA,WACA,WACS;AACT,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,KAAK,SAAS;AAC7B;AAYO,SAAS,YACd,OACA,WACA,WACG;AACH,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,UAAU,KAAK;AACxB;","names":[]}
@@ -5,7 +5,7 @@ import {
5
5
  err,
6
6
  getErrorMessage,
7
7
  ok
8
- } from "./chunk-NZN3SWSZ.js";
8
+ } from "./chunk-P2RI4DGX.js";
9
9
  import {
10
10
  findRepoRoot,
11
11
  getActiveWorkspaceRoot,
@@ -290,4 +290,4 @@ export {
290
290
  loadPapersRegistry,
291
291
  savePapersRegistry
292
292
  };
293
- //# sourceMappingURL=chunk-CG7OSI5P.js.map
293
+ //# sourceMappingURL=chunk-F3PIVN3B.js.map
@@ -2,7 +2,7 @@ import {
2
2
  CACHE_TIMEOUTS,
3
3
  createLogger,
4
4
  getTimeProvider
5
- } from "./chunk-NZN3SWSZ.js";
5
+ } from "./chunk-P2RI4DGX.js";
6
6
 
7
7
  // src/security/trust-types.ts
8
8
  import { z } from "zod";
@@ -610,4 +610,4 @@ export {
610
610
  resolveReputationGatingMode,
611
611
  gateWithReputation
612
612
  };
613
- //# sourceMappingURL=chunk-5GZ4UN5F.js.map
613
+ //# sourceMappingURL=chunk-GLG667IV.js.map
@@ -2,7 +2,7 @@ import {
2
2
  createLogger,
3
3
  err,
4
4
  ok
5
- } from "./chunk-NZN3SWSZ.js";
5
+ } from "./chunk-P2RI4DGX.js";
6
6
 
7
7
  // src/scm/token-resolver.ts
8
8
  import { execFile } from "node:child_process";
@@ -87,4 +87,4 @@ export {
87
87
  hasToken,
88
88
  getTokenEnvVars
89
89
  };
90
- //# sourceMappingURL=chunk-UDWZJY3V.js.map
90
+ //# sourceMappingURL=chunk-GPEGBNGB.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  GitHubProvider,
3
3
  ScmError
4
- } from "./chunk-SCXCJSTT.js";
4
+ } from "./chunk-3E4BZR3V.js";
5
5
  import {
6
6
  ROLE_DEFAULT_TRUST,
7
7
  ReputationCache,
@@ -12,10 +12,10 @@ import {
12
12
  resolveEnvMode,
13
13
  resolveReputationGatingMode,
14
14
  sanitizeInput
15
- } from "./chunk-5GZ4UN5F.js";
15
+ } from "./chunk-GLG667IV.js";
16
16
  import {
17
17
  hasToken
18
- } from "./chunk-UDWZJY3V.js";
18
+ } from "./chunk-GPEGBNGB.js";
19
19
  import {
20
20
  CLI_SUBPROCESS_TIMEOUTS,
21
21
  createLogger,
@@ -23,7 +23,7 @@ import {
23
23
  getErrorMessage,
24
24
  getTimeProvider,
25
25
  ok
26
- } from "./chunk-NZN3SWSZ.js";
26
+ } from "./chunk-P2RI4DGX.js";
27
27
 
28
28
  // src/security/firewall/firewall-policy-mode.ts
29
29
  import { z } from "zod";
@@ -2650,4 +2650,4 @@ export {
2650
2650
  IssueTriage,
2651
2651
  createIssueTriage
2652
2652
  };
2653
- //# sourceMappingURL=chunk-JYKRCQSU.js.map
2653
+ //# sourceMappingURL=chunk-H7PL2D5A.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-JRZEB4OQ.js";
3
+ } from "./chunk-U2C6V65K.js";
4
4
  import {
5
5
  sanitizeErrorDetails
6
6
  } from "./chunk-2NDA4DHW.js";
@@ -23,7 +23,7 @@ import {
23
23
  getTimeProvider,
24
24
  ok,
25
25
  resolveToolClassGuardMs
26
- } from "./chunk-NZN3SWSZ.js";
26
+ } from "./chunk-P2RI4DGX.js";
27
27
  import {
28
28
  getNexusDataDir,
29
29
  parseBoolValue
@@ -2342,4 +2342,4 @@ export {
2342
2342
  DEFAULT_CONSENSUS_CONFIG,
2343
2343
  ConsensusMetricsSchema
2344
2344
  };
2345
- //# sourceMappingURL=chunk-GYQIIAVM.js.map
2345
+ //# sourceMappingURL=chunk-K6IVHUEK.js.map
@@ -1,21 +1,21 @@
1
1
  import {
2
2
  SERVES_PROBE_PROMPT
3
- } from "./chunk-TRCYUQ4M.js";
3
+ } from "./chunk-PEN5XFMP.js";
4
4
  import {
5
5
  readOpenAICompatEndpoint,
6
6
  readOpenAICompatEnv
7
- } from "./chunk-BJXSG5YL.js";
7
+ } from "./chunk-4W4S6OBP.js";
8
8
  import {
9
9
  allOf
10
- } from "./chunk-OQB3XC5O.js";
10
+ } from "./chunk-EZNIYU5T.js";
11
11
  import {
12
12
  NODE_ENGINE_RANGE,
13
13
  VERSION,
14
14
  isNodeVersionSupported
15
- } from "./chunk-JRZEB4OQ.js";
15
+ } from "./chunk-U2C6V65K.js";
16
16
  import {
17
17
  claimGlobalRegistry
18
- } from "./chunk-TLFZPJOY.js";
18
+ } from "./chunk-YYVBEHM3.js";
19
19
  import {
20
20
  capitalize
21
21
  } from "./chunk-7LP6VJRP.js";
@@ -26,10 +26,10 @@ import {
26
26
  codexMcpServerAvailable,
27
27
  createAllAdapters,
28
28
  probeCli
29
- } from "./chunk-JYZNPK62.js";
29
+ } from "./chunk-P5ND7MWI.js";
30
30
  import {
31
31
  resolveGatewayEnv
32
- } from "./chunk-LZNYQYDU.js";
32
+ } from "./chunk-UR2KFP6P.js";
33
33
  import {
34
34
  getNexusTmpDir
35
35
  } from "./chunk-OITVVSWO.js";
@@ -59,7 +59,7 @@ import {
59
59
  resolveGatewayCostDeclaration,
60
60
  symbols,
61
61
  writeLine
62
- } from "./chunk-NZN3SWSZ.js";
62
+ } from "./chunk-P2RI4DGX.js";
63
63
  import {
64
64
  getLearningDir,
65
65
  getOutcomesFile,
@@ -1401,13 +1401,13 @@ async function runDoctorFix(result) {
1401
1401
  writeLine2("\u2500".repeat(40));
1402
1402
  let fixCount = 0;
1403
1403
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
1404
- const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-UNM34FGW.js");
1404
+ const { initDataDirectories: initDataDirectories2, describeDataDirFix: describeDataDirFix2 } = await import("./setup-data-dir-XJMN4ALO.js");
1405
1405
  const outcome = describeDataDirFix2(initDataDirectories2());
1406
1406
  writeLine2(outcome.line);
1407
1407
  if (outcome.counted) fixCount++;
1408
1408
  }
1409
1409
  if (!result.configFile.found) {
1410
- const { runConfigInitSync } = await import("./setup-config-XA756R2O.js");
1410
+ const { runConfigInitSync } = await import("./setup-config-3KBMBPCN.js");
1411
1411
  const configResult = runConfigInitSync(process.cwd(), false, false);
1412
1412
  if (configResult.success && configResult.created) {
1413
1413
  writeLine2(`\u2713 Generated config: ${configResult.path}`);
@@ -1503,4 +1503,4 @@ export {
1503
1503
  startStdioServer,
1504
1504
  closeServer
1505
1505
  };
1506
- //# sourceMappingURL=chunk-5XZCL7QT.js.map
1506
+ //# sourceMappingURL=chunk-LBYA22G5.js.map
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  createLogger,
6
6
  getTimeProvider
7
- } from "./chunk-NZN3SWSZ.js";
7
+ } from "./chunk-P2RI4DGX.js";
8
8
 
9
9
  // src/mcp/tools/scanner-registry-fetcher.ts
10
10
  import { z } from "zod";
@@ -740,4 +740,4 @@ export {
740
740
  generateSecurityPlan,
741
741
  buildPlanFromAnalysis
742
742
  };
743
- //# sourceMappingURL=chunk-3IBALX36.js.map
743
+ //# sourceMappingURL=chunk-LVL6WCWK.js.map