nexus-agents 2.162.0 → 2.163.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 (130) hide show
  1. package/dist/{child-mcp-config-GXWEIDJH.js → child-mcp-config-ZSVYMJTH.js} +3 -3
  2. package/dist/{chunk-BSGAU3WE.js → chunk-2EAKVHOL.js} +3 -3
  3. package/dist/{chunk-ZQP2VUQN.js → chunk-2LR2XP3B.js} +9 -9
  4. package/dist/{chunk-RQ4JK2YE.js → chunk-3EBDRAQW.js} +3 -3
  5. package/dist/{chunk-GMT6X3ED.js → chunk-3JWMDESZ.js} +3 -3
  6. package/dist/{chunk-VT562DIB.js → chunk-3RDE3OZ6.js} +7 -7
  7. package/dist/{chunk-CI5F3CJL.js → chunk-3ZXNPAUR.js} +2 -2
  8. package/dist/{chunk-ZZJIUJT4.js → chunk-47EFSSZK.js} +3 -3
  9. package/dist/{chunk-2U42PBUF.js → chunk-563FMXWL.js} +2 -2
  10. package/dist/{chunk-G5KOZAHM.js → chunk-5KFUWUMY.js} +2 -2
  11. package/dist/{chunk-7F6AMBM4.js → chunk-AM7EW7CP.js} +4 -4
  12. package/dist/{chunk-3KCSKD7P.js → chunk-AOXZ42SD.js} +2 -2
  13. package/dist/{chunk-V5MPFOT7.js → chunk-ARTIFRBA.js} +2 -2
  14. package/dist/{chunk-NL7SZQPW.js → chunk-AXTD4TFK.js} +5 -1
  15. package/dist/{chunk-NL7SZQPW.js.map → chunk-AXTD4TFK.js.map} +1 -1
  16. package/dist/{chunk-EKGN6UIH.js → chunk-B3FX6E7M.js} +37 -37
  17. package/dist/{chunk-MYIJLJQ7.js → chunk-CNGZ5N4W.js} +5 -5
  18. package/dist/{chunk-YRGEW5HH.js → chunk-D2NBIVAV.js} +5 -5
  19. package/dist/{chunk-VBL7BVUP.js → chunk-ENKFWBRH.js} +2 -2
  20. package/dist/{chunk-L6PB3464.js → chunk-HDLWUFKI.js} +2 -2
  21. package/dist/{chunk-YAJBZKCC.js → chunk-JZ3DVFEW.js} +7 -7
  22. package/dist/{chunk-Y6ZICYXS.js → chunk-K5NU57WE.js} +4 -4
  23. package/dist/{chunk-P23SETQP.js → chunk-K7GAI4WP.js} +2 -2
  24. package/dist/{chunk-FTPCUJUK.js → chunk-LJWB4Z7O.js} +2 -2
  25. package/dist/{chunk-A4XTT4AG.js → chunk-NDV5J3Z5.js} +281 -28
  26. package/dist/chunk-NDV5J3Z5.js.map +1 -0
  27. package/dist/{chunk-DY5QOBYH.js → chunk-NG5ZAI7W.js} +2 -2
  28. package/dist/{chunk-DQQTKATY.js → chunk-OEOBPWBH.js} +26 -9
  29. package/dist/chunk-OEOBPWBH.js.map +1 -0
  30. package/dist/{chunk-Z6ORP7BL.js → chunk-P4J6I5ZI.js} +2 -2
  31. package/dist/{chunk-YXSRBCA2.js → chunk-PRU452SV.js} +2 -2
  32. package/dist/{chunk-BHMKXBCY.js → chunk-S477DLWR.js} +4 -4
  33. package/dist/{chunk-IOWQ2KZK.js → chunk-SBCIKT64.js} +3 -3
  34. package/dist/{chunk-PYTWA2LR.js → chunk-SKJK44YC.js} +3 -3
  35. package/dist/{chunk-OFZYDOF3.js → chunk-U5E2JJ4F.js} +6 -6
  36. package/dist/{chunk-EPRHNYCO.js → chunk-UAK3OVSL.js} +2 -2
  37. package/dist/{chunk-FETTN45O.js → chunk-UEAG2PEQ.js} +2 -2
  38. package/dist/{chunk-RKLKUNRA.js → chunk-WRZ7HENW.js} +2 -2
  39. package/dist/{chunk-TXRPJ6DJ.js → chunk-Y6O4FB5V.js} +4 -4
  40. package/dist/{cli-circuit-breaker-MKP4EGJ3.js → cli-circuit-breaker-KUPKNGN2.js} +5 -5
  41. package/dist/cli.js +42 -42
  42. package/dist/{composite-router-E5HK2SPX.js → composite-router-F6YN34I7.js} +3 -3
  43. package/dist/{consensus-vote-53LNVJQX.js → consensus-vote-N4HVJT7S.js} +16 -16
  44. package/dist/{context-retriever-ZQXEWMHS.js → context-retriever-W6Z6JNEF.js} +9 -9
  45. package/dist/{doctor-deep-RW5FKXIQ.js → doctor-deep-MKKGB3KM.js} +4 -4
  46. package/dist/{expert-bridge-435SKR4I.js → expert-bridge-KWUVLYXR.js} +5 -5
  47. package/dist/factory-5TRDV3CD.js +15 -0
  48. package/dist/factory-UF6LR6R6.js +22 -0
  49. package/dist/{improvement-review-MO277SWX.js → improvement-review-K2FQ5K4H.js} +6 -6
  50. package/dist/index.d.ts +81 -25
  51. package/dist/index.js +31 -31
  52. package/dist/{init-opencode-TH5B5PWD.js → init-opencode-42DWDOPX.js} +7 -7
  53. package/dist/issue-triage-OHJZLCEG.js +18 -0
  54. package/dist/{learning-persistence-M3OTCCNI.js → learning-persistence-6D5GGT7D.js} +4 -2
  55. package/dist/{pr-reviewer-helpers-Z6MIXEHD.js → pr-reviewer-helpers-ZWGIWDFL.js} +5 -5
  56. package/dist/{registry-command-YXXJ3EYA.js → registry-command-X6FLUFKQ.js} +3 -3
  57. package/dist/{repo-security-plan-LOYQKXWA.js → repo-security-plan-K4IYY3OY.js} +4 -4
  58. package/dist/{research-helpers-synthesize-BIEZJYKV.js → research-helpers-synthesize-GBT6QZIP.js} +5 -5
  59. package/dist/{routing-memory-FD77RBPF.js → routing-memory-KDVKLC75.js} +3 -3
  60. package/dist/{session-memory-ZWRYRPK2.js → session-memory-HQ5KPXQG.js} +4 -4
  61. package/dist/{setup-command-HTBWLS2P.js → setup-command-USFTGMA3.js} +12 -12
  62. package/dist/setup-config-K66VKRCD.js +11 -0
  63. package/dist/{setup-custom-api-SHWRKXZG.js → setup-custom-api-6CG7HMRX.js} +4 -4
  64. package/dist/{tool-memory-2765TOOT.js → tool-memory-DAGKXCJA.js} +6 -6
  65. package/dist/{unified-registry-PBJ4ZVPL.js → unified-registry-GAGQ2VSX.js} +10 -10
  66. package/dist/{weather-report-SIF2QPOU.js → weather-report-ZYPHCFXL.js} +3 -3
  67. package/package.json +1 -1
  68. package/dist/chunk-A4XTT4AG.js.map +0 -1
  69. package/dist/chunk-DQQTKATY.js.map +0 -1
  70. package/dist/factory-BSELGB2U.js +0 -22
  71. package/dist/factory-PV4YEJXD.js +0 -15
  72. package/dist/issue-triage-ZAL27WBT.js +0 -18
  73. package/dist/setup-config-HTZVHPW2.js +0 -11
  74. /package/dist/{child-mcp-config-GXWEIDJH.js.map → child-mcp-config-ZSVYMJTH.js.map} +0 -0
  75. /package/dist/{chunk-BSGAU3WE.js.map → chunk-2EAKVHOL.js.map} +0 -0
  76. /package/dist/{chunk-ZQP2VUQN.js.map → chunk-2LR2XP3B.js.map} +0 -0
  77. /package/dist/{chunk-RQ4JK2YE.js.map → chunk-3EBDRAQW.js.map} +0 -0
  78. /package/dist/{chunk-GMT6X3ED.js.map → chunk-3JWMDESZ.js.map} +0 -0
  79. /package/dist/{chunk-VT562DIB.js.map → chunk-3RDE3OZ6.js.map} +0 -0
  80. /package/dist/{chunk-CI5F3CJL.js.map → chunk-3ZXNPAUR.js.map} +0 -0
  81. /package/dist/{chunk-ZZJIUJT4.js.map → chunk-47EFSSZK.js.map} +0 -0
  82. /package/dist/{chunk-2U42PBUF.js.map → chunk-563FMXWL.js.map} +0 -0
  83. /package/dist/{chunk-G5KOZAHM.js.map → chunk-5KFUWUMY.js.map} +0 -0
  84. /package/dist/{chunk-7F6AMBM4.js.map → chunk-AM7EW7CP.js.map} +0 -0
  85. /package/dist/{chunk-3KCSKD7P.js.map → chunk-AOXZ42SD.js.map} +0 -0
  86. /package/dist/{chunk-V5MPFOT7.js.map → chunk-ARTIFRBA.js.map} +0 -0
  87. /package/dist/{chunk-EKGN6UIH.js.map → chunk-B3FX6E7M.js.map} +0 -0
  88. /package/dist/{chunk-MYIJLJQ7.js.map → chunk-CNGZ5N4W.js.map} +0 -0
  89. /package/dist/{chunk-YRGEW5HH.js.map → chunk-D2NBIVAV.js.map} +0 -0
  90. /package/dist/{chunk-VBL7BVUP.js.map → chunk-ENKFWBRH.js.map} +0 -0
  91. /package/dist/{chunk-L6PB3464.js.map → chunk-HDLWUFKI.js.map} +0 -0
  92. /package/dist/{chunk-YAJBZKCC.js.map → chunk-JZ3DVFEW.js.map} +0 -0
  93. /package/dist/{chunk-Y6ZICYXS.js.map → chunk-K5NU57WE.js.map} +0 -0
  94. /package/dist/{chunk-P23SETQP.js.map → chunk-K7GAI4WP.js.map} +0 -0
  95. /package/dist/{chunk-FTPCUJUK.js.map → chunk-LJWB4Z7O.js.map} +0 -0
  96. /package/dist/{chunk-DY5QOBYH.js.map → chunk-NG5ZAI7W.js.map} +0 -0
  97. /package/dist/{chunk-Z6ORP7BL.js.map → chunk-P4J6I5ZI.js.map} +0 -0
  98. /package/dist/{chunk-YXSRBCA2.js.map → chunk-PRU452SV.js.map} +0 -0
  99. /package/dist/{chunk-BHMKXBCY.js.map → chunk-S477DLWR.js.map} +0 -0
  100. /package/dist/{chunk-IOWQ2KZK.js.map → chunk-SBCIKT64.js.map} +0 -0
  101. /package/dist/{chunk-PYTWA2LR.js.map → chunk-SKJK44YC.js.map} +0 -0
  102. /package/dist/{chunk-OFZYDOF3.js.map → chunk-U5E2JJ4F.js.map} +0 -0
  103. /package/dist/{chunk-EPRHNYCO.js.map → chunk-UAK3OVSL.js.map} +0 -0
  104. /package/dist/{chunk-FETTN45O.js.map → chunk-UEAG2PEQ.js.map} +0 -0
  105. /package/dist/{chunk-RKLKUNRA.js.map → chunk-WRZ7HENW.js.map} +0 -0
  106. /package/dist/{chunk-TXRPJ6DJ.js.map → chunk-Y6O4FB5V.js.map} +0 -0
  107. /package/dist/{cli-circuit-breaker-MKP4EGJ3.js.map → cli-circuit-breaker-KUPKNGN2.js.map} +0 -0
  108. /package/dist/{composite-router-E5HK2SPX.js.map → composite-router-F6YN34I7.js.map} +0 -0
  109. /package/dist/{consensus-vote-53LNVJQX.js.map → consensus-vote-N4HVJT7S.js.map} +0 -0
  110. /package/dist/{context-retriever-ZQXEWMHS.js.map → context-retriever-W6Z6JNEF.js.map} +0 -0
  111. /package/dist/{doctor-deep-RW5FKXIQ.js.map → doctor-deep-MKKGB3KM.js.map} +0 -0
  112. /package/dist/{expert-bridge-435SKR4I.js.map → expert-bridge-KWUVLYXR.js.map} +0 -0
  113. /package/dist/{factory-BSELGB2U.js.map → factory-5TRDV3CD.js.map} +0 -0
  114. /package/dist/{factory-PV4YEJXD.js.map → factory-UF6LR6R6.js.map} +0 -0
  115. /package/dist/{improvement-review-MO277SWX.js.map → improvement-review-K2FQ5K4H.js.map} +0 -0
  116. /package/dist/{init-opencode-TH5B5PWD.js.map → init-opencode-42DWDOPX.js.map} +0 -0
  117. /package/dist/{issue-triage-ZAL27WBT.js.map → issue-triage-OHJZLCEG.js.map} +0 -0
  118. /package/dist/{learning-persistence-M3OTCCNI.js.map → learning-persistence-6D5GGT7D.js.map} +0 -0
  119. /package/dist/{pr-reviewer-helpers-Z6MIXEHD.js.map → pr-reviewer-helpers-ZWGIWDFL.js.map} +0 -0
  120. /package/dist/{registry-command-YXXJ3EYA.js.map → registry-command-X6FLUFKQ.js.map} +0 -0
  121. /package/dist/{repo-security-plan-LOYQKXWA.js.map → repo-security-plan-K4IYY3OY.js.map} +0 -0
  122. /package/dist/{research-helpers-synthesize-BIEZJYKV.js.map → research-helpers-synthesize-GBT6QZIP.js.map} +0 -0
  123. /package/dist/{routing-memory-FD77RBPF.js.map → routing-memory-KDVKLC75.js.map} +0 -0
  124. /package/dist/{session-memory-ZWRYRPK2.js.map → session-memory-HQ5KPXQG.js.map} +0 -0
  125. /package/dist/{setup-command-HTBWLS2P.js.map → setup-command-USFTGMA3.js.map} +0 -0
  126. /package/dist/{setup-config-HTZVHPW2.js.map → setup-config-K66VKRCD.js.map} +0 -0
  127. /package/dist/{setup-custom-api-SHWRKXZG.js.map → setup-custom-api-6CG7HMRX.js.map} +0 -0
  128. /package/dist/{tool-memory-2765TOOT.js.map → tool-memory-DAGKXCJA.js.map} +0 -0
  129. /package/dist/{unified-registry-PBJ4ZVPL.js.map → unified-registry-GAGQ2VSX.js.map} +0 -0
  130. /package/dist/{weather-report-SIF2QPOU.js.map → weather-report-ZYPHCFXL.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  GitHubProvider,
3
3
  ScmError
4
- } from "./chunk-P23SETQP.js";
4
+ } from "./chunk-K7GAI4WP.js";
5
5
  import {
6
6
  ROLE_DEFAULT_TRUST,
7
7
  ReputationCache,
@@ -11,17 +11,17 @@ import {
11
11
  gateWithReputation,
12
12
  resolveReputationGatingMode,
13
13
  sanitizeInput
14
- } from "./chunk-YXSRBCA2.js";
14
+ } from "./chunk-PRU452SV.js";
15
15
  import {
16
16
  emitPolicyEvent
17
- } from "./chunk-DY5QOBYH.js";
17
+ } from "./chunk-NG5ZAI7W.js";
18
18
  import {
19
19
  CLI_SUBPROCESS_TIMEOUTS,
20
20
  createLogger,
21
21
  err,
22
22
  getTimeProvider,
23
23
  ok
24
- } from "./chunk-A4XTT4AG.js";
24
+ } from "./chunk-NDV5J3Z5.js";
25
25
 
26
26
  // src/security/trust-classifier.ts
27
27
  function mapAuthorAssociation(association) {
@@ -1211,4 +1211,4 @@ export {
1211
1211
  IssueTriage,
1212
1212
  createIssueTriage
1213
1213
  };
1214
- //# sourceMappingURL=chunk-YRGEW5HH.js.map
1214
+ //# sourceMappingURL=chunk-D2NBIVAV.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getRandomProvider,
3
3
  getTimeProvider
4
- } from "./chunk-A4XTT4AG.js";
4
+ } from "./chunk-NDV5J3Z5.js";
5
5
 
6
6
  // src/utils/id-utils.ts
7
7
  import { randomUUID } from "crypto";
@@ -24,4 +24,4 @@ export {
24
24
  generateHyphenId,
25
25
  generateUUID
26
26
  };
27
- //# sourceMappingURL=chunk-VBL7BVUP.js.map
27
+ //# sourceMappingURL=chunk-ENKFWBRH.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getErrorMessage
3
- } from "./chunk-A4XTT4AG.js";
3
+ } from "./chunk-NDV5J3Z5.js";
4
4
 
5
5
  // src/cli/setup-config.ts
6
6
  import { copyFileSync, existsSync, mkdirSync, writeFileSync } from "fs";
@@ -77,4 +77,4 @@ function ensureBackup(outputPath) {
77
77
  export {
78
78
  runConfigInitSync
79
79
  };
80
- //# sourceMappingURL=chunk-L6PB3464.js.map
80
+ //# sourceMappingURL=chunk-HDLWUFKI.js.map
@@ -5,24 +5,24 @@ import {
5
5
  planOptionalParams,
6
6
  requireApiKey,
7
7
  validateApiKeyPresence
8
- } from "./chunk-V5MPFOT7.js";
8
+ } from "./chunk-ARTIFRBA.js";
9
9
  import {
10
10
  CUSTOM_API_BASE_URL_ENV,
11
11
  CUSTOM_API_DEFAULT_MODEL,
12
12
  PROVIDER_ENV_KEYS,
13
13
  assertCustomApiHostResolvesPublic,
14
14
  validateCustomApiBaseUrl
15
- } from "./chunk-RKLKUNRA.js";
15
+ } from "./chunk-WRZ7HENW.js";
16
16
  import {
17
17
  CliCircuitBreaker,
18
18
  DEFAULT_CIRCUIT_BREAKER_CONFIG
19
- } from "./chunk-3KCSKD7P.js";
19
+ } from "./chunk-AOXZ42SD.js";
20
20
  import {
21
21
  getAvailabilityCache
22
- } from "./chunk-FTPCUJUK.js";
22
+ } from "./chunk-LJWB4Z7O.js";
23
23
  import {
24
24
  generateHyphenId
25
- } from "./chunk-VBL7BVUP.js";
25
+ } from "./chunk-ENKFWBRH.js";
26
26
  import {
27
27
  CLI_SUBPROCESS_TIMEOUTS,
28
28
  CLI_TIMEOUTS,
@@ -58,7 +58,7 @@ import {
58
58
  loadModelsDevSnapshot,
59
59
  ok,
60
60
  resolveCliAlias
61
- } from "./chunk-A4XTT4AG.js";
61
+ } from "./chunk-NDV5J3Z5.js";
62
62
 
63
63
  // src/cli-adapters/cli-to-model-adapter.ts
64
64
  var CliToModelAdapter = class {
@@ -4867,4 +4867,4 @@ export {
4867
4867
  SdkAdapter,
4868
4868
  createAutoAdapter
4869
4869
  };
4870
- //# sourceMappingURL=chunk-YAJBZKCC.js.map
4870
+ //# sourceMappingURL=chunk-JZ3DVFEW.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  OpenAIAdapter
3
- } from "./chunk-PYTWA2LR.js";
3
+ } from "./chunk-SKJK44YC.js";
4
4
  import {
5
5
  computeCostDetail,
6
6
  recordUsageEvent
7
- } from "./chunk-EPRHNYCO.js";
7
+ } from "./chunk-UAK3OVSL.js";
8
8
  import {
9
9
  ConfigError,
10
10
  createLogger,
@@ -12,7 +12,7 @@ import {
12
12
  getErrorMessage,
13
13
  getTimeProvider,
14
14
  ok
15
- } from "./chunk-A4XTT4AG.js";
15
+ } from "./chunk-NDV5J3Z5.js";
16
16
 
17
17
  // src/config/opencode-bridge.ts
18
18
  import { readFileSync } from "fs";
@@ -194,4 +194,4 @@ export {
194
194
  discoverModels,
195
195
  buildOpenAICompatAdapters
196
196
  };
197
- //# sourceMappingURL=chunk-Y6ZICYXS.js.map
197
+ //# sourceMappingURL=chunk-K5NU57WE.js.map
@@ -4,7 +4,7 @@ import {
4
4
  err,
5
5
  getErrorMessage,
6
6
  ok
7
- } from "./chunk-A4XTT4AG.js";
7
+ } from "./chunk-NDV5J3Z5.js";
8
8
 
9
9
  // src/scm/types.ts
10
10
  var ScmError = class extends Error {
@@ -263,4 +263,4 @@ export {
263
263
  ScmError,
264
264
  GitHubProvider
265
265
  };
266
- //# sourceMappingURL=chunk-P23SETQP.js.map
266
+ //# sourceMappingURL=chunk-K7GAI4WP.js.map
@@ -3,7 +3,7 @@ import {
3
3
  MODEL_IDS,
4
4
  getTimeProvider,
5
5
  resolveModelIdentitySync
6
- } from "./chunk-A4XTT4AG.js";
6
+ } from "./chunk-NDV5J3Z5.js";
7
7
 
8
8
  // src/config/model-availability.ts
9
9
  var DEFAULT_TTL_MS = 6e4;
@@ -150,4 +150,4 @@ export {
150
150
  resetAvailabilityCache,
151
151
  filterAvailableModels
152
152
  };
153
- //# sourceMappingURL=chunk-FTPCUJUK.js.map
153
+ //# sourceMappingURL=chunk-LJWB4Z7O.js.map
@@ -1,8 +1,9 @@
1
1
  import {
2
2
  ensureLearningDir,
3
3
  getDecisionCostFile,
4
+ getModelSelectionShadowFile,
4
5
  isPersistenceEnabled
5
- } from "./chunk-NL7SZQPW.js";
6
+ } from "./chunk-AXTD4TFK.js";
6
7
  import {
7
8
  nexusDataPath
8
9
  } from "./chunk-DHVMSIT5.js";
@@ -2612,7 +2613,7 @@ function setDefaultRegistry(registry) {
2612
2613
  }
2613
2614
  async function reloadDefaultRegistry() {
2614
2615
  globalRegistry = buildDefaultRegistry();
2615
- const { resetGlobalRegistry } = await import("./unified-registry-PBJ4ZVPL.js");
2616
+ const { resetGlobalRegistry } = await import("./unified-registry-GAGQ2VSX.js");
2616
2617
  resetGlobalRegistry();
2617
2618
  return globalRegistry;
2618
2619
  }
@@ -9018,14 +9019,14 @@ function detectSuccessPatterns(groups, threshold) {
9018
9019
  const patterns = [];
9019
9020
  for (const g of groups) {
9020
9021
  const successCount = g.outcomes.filter((o) => o.success).length;
9021
- const successRate2 = successCount / g.outcomes.length;
9022
- if (successRate2 >= threshold) {
9022
+ const successRate3 = successCount / g.outcomes.length;
9023
+ if (successRate3 >= threshold) {
9023
9024
  patterns.push({
9024
9025
  cli: g.cli,
9025
9026
  category: g.category,
9026
9027
  patternType: "success-rate",
9027
9028
  action: "boost",
9028
- metric: successRate2,
9029
+ metric: successRate3,
9029
9030
  observationCount: g.outcomes.length
9030
9031
  });
9031
9032
  }
@@ -9218,10 +9219,10 @@ var StrategyDistiller = class {
9218
9219
  }
9219
9220
  /** Convert rule metrics into ModelPerformance for RoutingMemory. */
9220
9221
  ruleToPerformance(rule) {
9221
- const successRate2 = rule.patternType === "success-rate" ? rule.metric : 1 - rule.metric;
9222
+ const successRate3 = rule.patternType === "success-rate" ? rule.metric : 1 - rule.metric;
9222
9223
  return {
9223
9224
  avgQuality: rule.confidence,
9224
- successRate: Math.max(0, Math.min(1, successRate2)),
9225
+ successRate: Math.max(0, Math.min(1, successRate3)),
9225
9226
  avgLatencyMs: 0,
9226
9227
  avgTokens: 0,
9227
9228
  observations: rule.observationCount
@@ -10004,9 +10005,11 @@ var CompositeRouterConfigSchema = z11.object({
10004
10005
  maxCostUsd: z11.number().positive(),
10005
10006
  maxLatencyMs: z11.number().positive(),
10006
10007
  /** Per-task-class cost ceilings in USD, keyed by TaskCategory (#4196).
10008
+ * Keys are validated against the TaskCategory enum (#4214) so a typo'd
10009
+ * class fails config parsing instead of silently configuring nothing.
10007
10010
  * Default: absent → no ceiling (OFF/unlimited). Enforced only under
10008
10011
  * billingMode 'api'; missing candidate pricing fails CLOSED. */
10009
- taskClassMaxCostUsd: z11.record(z11.string(), z11.number().positive())
10012
+ taskClassMaxCostUsd: z11.partialRecord(TaskCategorySchema, z11.number().positive())
10010
10013
  }).partial().optional(),
10011
10014
  /** LinUCB exploration parameter (default: 1.0) */
10012
10015
  linucbAlpha: z11.number().positive().default(1),
@@ -12417,9 +12420,9 @@ function getAdaptiveBonus(cli, category, config) {
12417
12420
  const cliName = cli;
12418
12421
  const outcomes = queryWithLookback(store, cliName, category, cfg);
12419
12422
  if (outcomes.length < cfg.coldStartThreshold) return 0;
12420
- const successRate2 = outcomes.filter((o) => o.success).length / outcomes.length;
12423
+ const successRate3 = outcomes.filter((o) => o.success).length / outcomes.length;
12421
12424
  const FIXED_BASELINE = 0.7;
12422
- const delta = successRate2 - FIXED_BASELINE;
12425
+ const delta = successRate3 - FIXED_BASELINE;
12423
12426
  const FULL_CONFIDENCE_SAMPLES2 = 50;
12424
12427
  const windowedConfidence = Math.min(1, outcomes.length / FULL_CONFIDENCE_SAMPLES2);
12425
12428
  const maxBonus = Math.min(cfg.maxBonusAdjustment * windowedConfidence, cfg.maxBonusAdjustment);
@@ -12694,17 +12697,17 @@ function buildExpertPerformance() {
12694
12697
  const successes = outcomes.filter((o) => o.success).length;
12695
12698
  const totalDuration = outcomes.reduce((s, o) => s + o.durationMs, 0);
12696
12699
  const dominantErrorPattern = findDominantError(outcomes.filter((o) => !o.success));
12697
- const successRate2 = successes / outcomes.length;
12700
+ const successRate3 = successes / outcomes.length;
12698
12701
  const consecutiveFailures = countTrailingFailures(outcomes);
12699
12702
  const lastSuccess = [...outcomes].reverse().find((o) => o.success);
12700
12703
  const lastSuccessAt = lastSuccess !== void 0 ? new Date(lastSuccess.timestamp).toISOString() : void 0;
12701
12704
  entries.push({
12702
12705
  role,
12703
12706
  totalTasks: outcomes.length,
12704
- successRate: successRate2,
12707
+ successRate: successRate3,
12705
12708
  avgDurationMs: Math.round(totalDuration / outcomes.length),
12706
12709
  consecutiveFailures,
12707
- degraded: successRate2 < 0.5,
12710
+ degraded: successRate3 < 0.5,
12708
12711
  ...dominantErrorPattern !== void 0 ? { dominantErrorPattern } : {},
12709
12712
  ...lastSuccessAt !== void 0 ? { lastSuccessAt } : {}
12710
12713
  });
@@ -13684,6 +13687,169 @@ function resolveModelForTier(cliName, tier, opts = {}) {
13684
13687
  return scored[0]?.id ?? getDefaultModelForCli(cliName);
13685
13688
  }
13686
13689
 
13690
+ // src/cli-adapters/model-selection-shadow.ts
13691
+ import { appendFileSync as appendFileSync2, existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
13692
+ import { z as z19 } from "zod";
13693
+ function isRouteModelShadowEnabled() {
13694
+ return process.env["NEXUS_ROUTE_MODEL_SHADOW"] === "1" && isPersistenceEnabled();
13695
+ }
13696
+ var MODEL_SELECTION_SHADOW_SCHEMA_VERSION = 1;
13697
+ var READ_LOOKBACK_DAYS = 30;
13698
+ var READ_LOOKBACK_MS = READ_LOOKBACK_DAYS * 24 * 60 * 60 * 1e3;
13699
+ var ModelTierSchema = z19.enum(["fast", "balanced", "powerful"]);
13700
+ var ModelSelectionShadowRecordSchema = z19.object({
13701
+ schema: z19.literal(MODEL_SELECTION_SHADOW_SCHEMA_VERSION),
13702
+ /** ISO timestamp of the outcome join. */
13703
+ timestamp: z19.string().min(1),
13704
+ /** Display slot of the routed CLI (api:* arms collapse to their slot). */
13705
+ cli: z19.string().min(1).max(40),
13706
+ /** Difficulty tier the ZeroRouter computed for the task. */
13707
+ tier: ModelTierSchema,
13708
+ /** Model the live decision actually used (or the CLI default when route-time selection is off). */
13709
+ actualModel: z19.string().min(1).max(120),
13710
+ /** Model `resolveModelForTier` WOULD have picked (never executed). */
13711
+ shadowModel: z19.string().min(1).max(120),
13712
+ /** Whether shadow and actual agree. */
13713
+ agree: z19.boolean(),
13714
+ /** Whether the actually-executed decision succeeded. */
13715
+ success: z19.boolean(),
13716
+ /** Measured cost of the actual execution, when available (unmeasured today on the routing path). */
13717
+ costUsd: z19.number().nonnegative().optional()
13718
+ });
13719
+ function computeModelSelectionShadow(cli, tier, actualModel) {
13720
+ const shadowModel = resolveModelForTier(cli, tier);
13721
+ const actual = actualModel ?? getDefaultModelForCli(cli);
13722
+ return { cli, tier, actualModel: actual, shadowModel, agree: shadowModel === actual };
13723
+ }
13724
+ var shadowFailureCount = 0;
13725
+ function recordModelSelectionShadowFailure() {
13726
+ return ++shadowFailureCount;
13727
+ }
13728
+ var persistLogger = createLogger({ component: "ModelSelectionShadow" });
13729
+ function persistModelSelectionShadowRecord(record) {
13730
+ try {
13731
+ ensureLearningDir();
13732
+ appendFileSync2(getModelSelectionShadowFile(), JSON.stringify(record) + "\n", "utf-8");
13733
+ } catch (err2) {
13734
+ recordModelSelectionShadowFailure();
13735
+ persistLogger.warn("Failed to persist model-selection shadow record (ignored)", {
13736
+ error: getErrorMessage(err2)
13737
+ });
13738
+ }
13739
+ }
13740
+ function readModelSelectionShadowRecords() {
13741
+ const file = getModelSelectionShadowFile();
13742
+ if (!existsSync7(file)) return [];
13743
+ const records = [];
13744
+ try {
13745
+ const cutoff = Date.now() - READ_LOOKBACK_MS;
13746
+ const lines = readFileSync6(file, "utf-8").split("\n").filter((l) => l.trim().length > 0);
13747
+ for (const line of lines) {
13748
+ let parsed;
13749
+ try {
13750
+ parsed = JSON.parse(line);
13751
+ } catch {
13752
+ continue;
13753
+ }
13754
+ const result = ModelSelectionShadowRecordSchema.safeParse(parsed);
13755
+ if (!result.success) continue;
13756
+ const ts = Date.parse(result.data.timestamp);
13757
+ if (Number.isNaN(ts) || ts < cutoff) continue;
13758
+ records.push(result.data);
13759
+ }
13760
+ } catch (err2) {
13761
+ persistLogger.warn("Failed to read model-selection shadow records (ignored)", {
13762
+ error: getErrorMessage(err2)
13763
+ });
13764
+ }
13765
+ return records;
13766
+ }
13767
+
13768
+ // src/cli-adapters/model-selection-readiness.ts
13769
+ var DEFAULT_MODEL_SELECTION_READINESS_CONFIG = {
13770
+ minDivergingDecisions: 50,
13771
+ minSuccessDelta: 0.05,
13772
+ minCostSamples: 10
13773
+ };
13774
+ function successRate2(t) {
13775
+ return t.count === 0 ? 0 : t.successes / t.count;
13776
+ }
13777
+ function summarizeModelSelectionShadow(records) {
13778
+ const agree = { count: 0, successes: 0 };
13779
+ const diverge = { count: 0, successes: 0 };
13780
+ let costSamples = 0;
13781
+ let costTotal = 0;
13782
+ for (const r of records) {
13783
+ const cohort = r.agree ? agree : diverge;
13784
+ cohort.count++;
13785
+ if (r.success) cohort.successes++;
13786
+ if (r.costUsd !== void 0) {
13787
+ costSamples++;
13788
+ costTotal += r.costUsd;
13789
+ }
13790
+ }
13791
+ const agreeSuccessRate = successRate2(agree);
13792
+ const divergeSuccessRate = successRate2(diverge);
13793
+ const successDelta = agree.count === 0 || diverge.count === 0 ? 0 : agreeSuccessRate - divergeSuccessRate;
13794
+ return {
13795
+ total: records.length,
13796
+ agreeing: agree.count,
13797
+ diverging: diverge.count,
13798
+ agreeSuccessRate,
13799
+ divergeSuccessRate,
13800
+ successDelta,
13801
+ costSamples,
13802
+ meanCostUsd: costSamples === 0 ? 0 : costTotal / costSamples
13803
+ };
13804
+ }
13805
+ function evaluateModelSelectionReadiness(records, config = DEFAULT_MODEL_SELECTION_READINESS_CONFIG) {
13806
+ const s = summarizeModelSelectionShadow(records);
13807
+ const criteria = [
13808
+ {
13809
+ name: "volume",
13810
+ met: s.diverging >= config.minDivergingDecisions,
13811
+ detail: `${String(s.diverging)} shadow-diverging decisions (need \u2265 ${String(config.minDivergingDecisions)})`
13812
+ },
13813
+ {
13814
+ name: "success-delta",
13815
+ met: s.successDelta >= config.minSuccessDelta,
13816
+ detail: `agree\u2212diverge success delta ${s.successDelta.toFixed(2)} (agree ${s.agreeSuccessRate.toFixed(2)} over ${String(s.agreeing)}, diverge ${s.divergeSuccessRate.toFixed(2)} over ${String(s.diverging)}; need \u2265 ${config.minSuccessDelta.toFixed(2)})`
13817
+ },
13818
+ {
13819
+ name: "cost-measured",
13820
+ met: s.costSamples >= config.minCostSamples,
13821
+ detail: `${String(s.costSamples)} decisions with measured costUsd, mean $${s.meanCostUsd.toFixed(4)} (need \u2265 ${String(config.minCostSamples)})`
13822
+ }
13823
+ ];
13824
+ const blockers = criteria.filter((c) => !c.met).map((c) => c.name);
13825
+ return { ready: blockers.length === 0, criteria, blockers };
13826
+ }
13827
+ var readinessLogged = false;
13828
+ function logModelSelectionReadinessOnce(logger14) {
13829
+ if (readinessLogged) return;
13830
+ readinessLogged = true;
13831
+ try {
13832
+ const records = readModelSelectionShadowRecords();
13833
+ const summary = summarizeModelSelectionShadow(records);
13834
+ const verdict = evaluateModelSelectionReadiness(records);
13835
+ logger14.info("route-model-selection shadow readiness", {
13836
+ ready: verdict.ready,
13837
+ blockers: verdict.blockers,
13838
+ total: summary.total,
13839
+ diverging: summary.diverging,
13840
+ successDelta: summary.successDelta,
13841
+ agreeSuccessRate: summary.agreeSuccessRate,
13842
+ divergeSuccessRate: summary.divergeSuccessRate,
13843
+ costSamples: summary.costSamples,
13844
+ meanCostUsd: summary.meanCostUsd
13845
+ });
13846
+ } catch (err2) {
13847
+ logger14.warn("route-model-selection readiness signal failed (non-fatal)", {
13848
+ error: getErrorMessage(err2)
13849
+ });
13850
+ }
13851
+ }
13852
+
13687
13853
  // src/cli-adapters/composite-router-outcome.ts
13688
13854
  var sharedAnalyzer3 = createSharedTaskAnalyzer();
13689
13855
  function recordBanditOutcome(cliName, task, reward, deps) {
@@ -13892,6 +14058,13 @@ var CompositeRouter = class _CompositeRouter {
13892
14058
  lastRoutedTask;
13893
14059
  // Track last traceId for metrics correlation (Issue #559)
13894
14060
  lastTraceId;
14061
+ /**
14062
+ * Pending model-selection shadow comparison awaiting its outcome join
14063
+ * (#4197). Keyed by task content like {@link lastRoutedTask}; persisted with
14064
+ * `success` when `recordDifficultyOutcome` reports the matching outcome.
14065
+ * The task content itself is never persisted.
14066
+ */
14067
+ pendingModelShadow;
13895
14068
  constructor(adapters, config, logger14) {
13896
14069
  const {
13897
14070
  preferenceRouterConfig,
@@ -14076,7 +14249,7 @@ var CompositeRouter = class _CompositeRouter {
14076
14249
  */
14077
14250
  async consultUnifiedContext(task) {
14078
14251
  try {
14079
- const { getContextForTask, inferTaskCategory } = await import("./context-retriever-ZQXEWMHS.js");
14252
+ const { getContextForTask, inferTaskCategory } = await import("./context-retriever-W6Z6JNEF.js");
14080
14253
  const ctx = await getContextForTask({
14081
14254
  task: task.content,
14082
14255
  category: inferTaskCategory(task.content),
@@ -14200,12 +14373,16 @@ var CompositeRouter = class _CompositeRouter {
14200
14373
  return pipelineResult;
14201
14374
  }
14202
14375
  this.trackLastRoutedTask(task, pipelineResult.value);
14203
- return this.buildRoutingDecision({
14376
+ const decisionResult = this.buildRoutingDecision({
14204
14377
  ...pipelineResult.value,
14205
14378
  taskProfile,
14206
14379
  stagesExecuted,
14207
14380
  startTime
14208
14381
  });
14382
+ if (decisionResult.ok) {
14383
+ this.trackModelSelectionShadow(task, decisionResult.value);
14384
+ }
14385
+ return decisionResult;
14209
14386
  } catch (error) {
14210
14387
  return this.handleRoutingError(error, stagesExecuted);
14211
14388
  }
@@ -14291,6 +14468,80 @@ var CompositeRouter = class _CompositeRouter {
14291
14468
  };
14292
14469
  }
14293
14470
  }
14471
+ /**
14472
+ * Compute the model-selection SHADOW comparison for a routed decision
14473
+ * (#4197): what `resolveModelForTier` WOULD have picked vs the model the
14474
+ * decision actually carries (or the CLI default the adapter will resolve).
14475
+ * Held pending until `recordDifficultyOutcome` supplies the outcome, then
14476
+ * persisted to the dedicated shadow log. Gated behind
14477
+ * `NEXUS_ROUTE_MODEL_SHADOW=1` (default OFF). NEVER affects the live
14478
+ * decision — any failure increments the shadow-failure counter and is
14479
+ * logged, not thrown into the routing path.
14480
+ *
14481
+ * Tasks with a PINNED model (`CliTask.model`) are SKIPPED entirely: the
14482
+ * adapter executes the pinned model (base-adapter), not the CLI default the
14483
+ * comparison would otherwise assume, so a pinned run says nothing about the
14484
+ * tier selector — sampling it would mislabel the agree/diverge cohorts and
14485
+ * pad the volume criterion with garbage (#4218 review).
14486
+ */
14487
+ trackModelSelectionShadow(task, decision) {
14488
+ try {
14489
+ if (!isRouteModelShadowEnabled() || decision.difficultyTier === void 0) return;
14490
+ if (task.model !== void 0) return;
14491
+ logModelSelectionReadinessOnce(this.logger);
14492
+ const comparison = computeModelSelectionShadow(
14493
+ routingArmDisplaySlot(decision.cliName),
14494
+ decision.difficultyTier,
14495
+ decision.model
14496
+ );
14497
+ this.pendingModelShadow = { ...comparison, taskContent: task.content };
14498
+ this.logger.debug("Model-selection shadow computed (#4197)", {
14499
+ cli: comparison.cli,
14500
+ tier: comparison.tier,
14501
+ actualModel: comparison.actualModel,
14502
+ shadowModel: comparison.shadowModel,
14503
+ agree: comparison.agree
14504
+ });
14505
+ } catch (error) {
14506
+ const failures = recordModelSelectionShadowFailure();
14507
+ this.logger.warn("Model-selection shadow failed (non-fatal, #4197)", {
14508
+ error: getErrorMessage(error),
14509
+ failures
14510
+ });
14511
+ }
14512
+ }
14513
+ /**
14514
+ * Join a pending model-selection shadow comparison with its task outcome and
14515
+ * persist the completed record (#4197). Matches by task content, mirroring
14516
+ * {@link getDifficultyInfo}'s lastRoutedTask join. `costUsd` is deliberately
14517
+ * absent: the routing outcome path measures no per-decision cost today, and
14518
+ * the readiness gate's cost criterion stays fail-closed until it does.
14519
+ * Exception-guarded — an outcome-join failure never breaks outcome recording.
14520
+ */
14521
+ joinModelSelectionShadowOutcome(task, success) {
14522
+ const pending = this.pendingModelShadow;
14523
+ if (pending === void 0) return;
14524
+ if (pending.taskContent !== task.content) return;
14525
+ this.pendingModelShadow = void 0;
14526
+ try {
14527
+ persistModelSelectionShadowRecord({
14528
+ schema: MODEL_SELECTION_SHADOW_SCHEMA_VERSION,
14529
+ timestamp: new Date(getTimeProvider().now()).toISOString(),
14530
+ cli: pending.cli,
14531
+ tier: pending.tier,
14532
+ actualModel: pending.actualModel,
14533
+ shadowModel: pending.shadowModel,
14534
+ agree: pending.agree,
14535
+ success
14536
+ });
14537
+ } catch (error) {
14538
+ const failures = recordModelSelectionShadowFailure();
14539
+ this.logger.warn("Model-selection shadow outcome join failed (non-fatal, #4197)", {
14540
+ error: getErrorMessage(error),
14541
+ failures
14542
+ });
14543
+ }
14544
+ }
14294
14545
  buildRoutingDecision(params) {
14295
14546
  const selectedAdapter = this.adapters.get(params.selectedCli);
14296
14547
  if (selectedAdapter === void 0) {
@@ -14371,6 +14622,7 @@ var CompositeRouter = class _CompositeRouter {
14371
14622
  }
14372
14623
  recordDifficultyOutcome(task, success, qualityScore) {
14373
14624
  recordZeroRouterOutcome(task, success, qualityScore, this.getOutcomeDependencies());
14625
+ this.joinModelSelectionShadowOutcome(task, success);
14374
14626
  }
14375
14627
  hasMinimumPreferenceData() {
14376
14628
  return hasMinimumPreferenceData(this.getOutcomeDependencies());
@@ -14501,7 +14753,7 @@ import { dirname as dirname5 } from "path";
14501
14753
  import { mkdirSync as mkdirSync3 } from "fs";
14502
14754
 
14503
14755
  // src/context/mobimem-types.ts
14504
- import { z as z19 } from "zod";
14756
+ import { z as z20 } from "zod";
14505
14757
  var DEFAULT_MOBIMEM_CONFIG = {
14506
14758
  dbPath: ":memory:",
14507
14759
  maxProfileEntries: 100,
@@ -14513,15 +14765,15 @@ var DEFAULT_MOBIMEM_CONFIG = {
14513
14765
  minExperienceSuccessRate: 0.7,
14514
14766
  autoEviction: true
14515
14767
  };
14516
- var MobiMemConfigSchema = z19.object({
14517
- dbPath: z19.string(),
14518
- maxProfileEntries: z19.number().int().positive().default(100),
14519
- maxExperiencePatterns: z19.number().int().positive().default(500),
14520
- maxActionCacheEntries: z19.number().int().positive().default(1e3),
14521
- actionCacheTtlMs: z19.number().int().positive().default(36e5),
14522
- minProfileConfidence: z19.number().min(0).max(1).default(0.6),
14523
- minExperienceSuccessRate: z19.number().min(0).max(1).default(0.7),
14524
- autoEviction: z19.boolean().default(true)
14768
+ var MobiMemConfigSchema = z20.object({
14769
+ dbPath: z20.string(),
14770
+ maxProfileEntries: z20.number().int().positive().default(100),
14771
+ maxExperiencePatterns: z20.number().int().positive().default(500),
14772
+ maxActionCacheEntries: z20.number().int().positive().default(1e3),
14773
+ actionCacheTtlMs: z20.number().int().positive().default(36e5),
14774
+ minProfileConfidence: z20.number().min(0).max(1).default(0.6),
14775
+ minExperienceSuccessRate: z20.number().min(0).max(1).default(0.7),
14776
+ autoEviction: z20.boolean().default(true)
14525
14777
  });
14526
14778
 
14527
14779
  // src/context/mobimem-impl.ts
@@ -14541,9 +14793,9 @@ function generatePatternKey(taskType, actionSequence, contextSignature) {
14541
14793
  function hashInput(input) {
14542
14794
  return createHash2("sha256").update(JSON.stringify(input)).digest("hex");
14543
14795
  }
14544
- function calculatePatternScore(successRate2, contextMatches, attemptCount) {
14796
+ function calculatePatternScore(successRate3, contextMatches, attemptCount) {
14545
14797
  const contextMatch = contextMatches ? 1 : 0.5;
14546
- return successRate2 * contextMatch * Math.log10(attemptCount + 1);
14798
+ return successRate3 * contextMatch * Math.log10(attemptCount + 1);
14547
14799
  }
14548
14800
  function computeSuccessRate(successCount, attemptCount) {
14549
14801
  return attemptCount > 0 ? successCount / attemptCount : 0;
@@ -15402,6 +15654,7 @@ export {
15402
15654
  loadModelsDevSnapshot,
15403
15655
  loadGeneratedRegistryEntries,
15404
15656
  TASK_CATEGORIES,
15657
+ TaskCategorySchema,
15405
15658
  TASK_SPECIALIZATION_MATRIX,
15406
15659
  detectTaskCategory,
15407
15660
  CLI_TIMEOUTS,
@@ -15585,4 +15838,4 @@ export {
15585
15838
  AgentCapability,
15586
15839
  OrchestratorError
15587
15840
  };
15588
- //# sourceMappingURL=chunk-A4XTT4AG.js.map
15841
+ //# sourceMappingURL=chunk-NDV5J3Z5.js.map