nexus-agents 8.89.3 → 8.90.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.
- package/dist/{ast-rule-runner-AMZCLKRV.js → ast-rule-runner-SD665GB7.js} +3 -3
- package/dist/{child-mcp-config-7DSYI325.js → child-mcp-config-BG3QNALD.js} +2 -2
- package/dist/{chunk-5UCGVAEZ.js → chunk-2N7XWZPW.js} +4 -4
- package/dist/{chunk-BJXSG5YL.js → chunk-4KMNLWAC.js} +4 -4
- package/dist/{chunk-QX42N7TE.js → chunk-4PMYNW3G.js} +2 -2
- package/dist/{chunk-3PQIIMHN.js → chunk-5GI6Z5VE.js} +63 -23
- package/dist/chunk-5GI6Z5VE.js.map +1 -0
- package/dist/{chunk-TLFZPJOY.js → chunk-C6Q2NUIH.js} +4 -4
- package/dist/{chunk-OQB3XC5O.js → chunk-EZNIYU5T.js} +7 -2
- package/dist/{chunk-OQB3XC5O.js.map → chunk-EZNIYU5T.js.map} +1 -1
- package/dist/{chunk-NZN3SWSZ.js → chunk-F2H3MCEV.js} +32 -8
- package/dist/{chunk-NZN3SWSZ.js.map → chunk-F2H3MCEV.js.map} +1 -1
- package/dist/{chunk-EKZ6V7SE.js → chunk-FPX55ON5.js} +7 -7
- package/dist/{chunk-KQE7EFBF.js → chunk-HBXAYO3C.js} +5 -5
- package/dist/{chunk-JYKRCQSU.js → chunk-HD3FTCV4.js} +5 -5
- package/dist/{chunk-AXBEG6VW.js → chunk-HPE3UQLT.js} +4 -4
- package/dist/{chunk-UDWZJY3V.js → chunk-HUCILYVO.js} +2 -2
- package/dist/{chunk-MS5VFQE3.js → chunk-I3SCYF5R.js} +27 -13
- package/dist/chunk-I3SCYF5R.js.map +1 -0
- package/dist/{chunk-4IV25ZUM.js → chunk-IDASIJE6.js} +2 -2
- package/dist/{chunk-MYZGLD7Y.js → chunk-J3HT4YDM.js} +11 -11
- package/dist/{chunk-V76TXFRC.js → chunk-JG4DC2TZ.js} +5 -3
- package/dist/chunk-JG4DC2TZ.js.map +1 -0
- package/dist/{chunk-SCXCJSTT.js → chunk-JWHIFEI3.js} +2 -2
- package/dist/{chunk-LZNYQYDU.js → chunk-KCWEMSU2.js} +2 -2
- package/dist/{chunk-6FFBX665.js → chunk-NFP7WQ22.js} +2 -2
- package/dist/{chunk-ILA4UGXI.js → chunk-NMZ5ZKEO.js} +2 -2
- package/dist/{chunk-LFFXUHX3.js → chunk-O3MSZUQM.js} +2 -2
- package/dist/{chunk-Z5VUMKF5.js → chunk-OJM75DDY.js} +3 -3
- package/dist/{chunk-KSCQRZJZ.js → chunk-OX4L42RL.js} +3 -3
- package/dist/{chunk-5GZ4UN5F.js → chunk-QCWY3GTZ.js} +2 -2
- package/dist/{chunk-PENEGF75.js → chunk-RMDG3OFS.js} +2 -2
- package/dist/{chunk-CG7OSI5P.js → chunk-S6FK47MZ.js} +2 -2
- package/dist/{chunk-XU2SJKFK.js → chunk-SMKBETIX.js} +2 -2
- package/dist/{chunk-ZTTBGME2.js → chunk-VI5TF3KF.js} +2 -2
- package/dist/{chunk-JYZNPK62.js → chunk-VIDSDHSQ.js} +8 -8
- package/dist/{chunk-3IBALX36.js → chunk-VLBXRQIA.js} +2 -2
- package/dist/{chunk-TRCYUQ4M.js → chunk-WDGEJIWW.js} +2 -2
- package/dist/{chunk-NNHRMVZU.js → chunk-XEYZRY4C.js} +49 -48
- package/dist/{chunk-NNHRMVZU.js.map → chunk-XEYZRY4C.js.map} +1 -1
- package/dist/{chunk-XJAGCUMD.js → chunk-ZP7LYABJ.js} +2 -2
- package/dist/{chunk-VM4HZT3B.js → chunk-ZVHJMROO.js} +4 -4
- package/dist/{cli-circuit-breaker-MCQG3PQK.js → cli-circuit-breaker-GOH6U32K.js} +3 -3
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +89 -85
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-QAYCHEFG.js → composite-router-RMEHBA3J.js} +2 -2
- package/dist/{consensus-vote-EIV5TDPY.js → consensus-vote-23XXJUDP.js} +17 -17
- package/dist/{consensus-vote-types-DhmacUE7.d.ts → consensus-vote-types-BdptpuQK.d.ts} +6 -0
- package/dist/{context-retriever-UXQCDDRY.js → context-retriever-TWAN22PW.js} +8 -8
- package/dist/{doctor-deep-QRLRDFM4.js → doctor-deep-HRZ77NYS.js} +4 -3
- package/dist/{doctor-live-CUKBQSSH.js → doctor-live-VGOABDSJ.js} +10 -10
- package/dist/{expert-bridge-ZG2IA3RJ.js → expert-bridge-PFR7ZNWK.js} +4 -4
- package/dist/{factory-RQEHJ4AW.js → factory-DJPYG3WR.js} +9 -9
- package/dist/{factory-FPNYFKXU.js → factory-JCVKAI7P.js} +5 -5
- package/dist/{improvement-review-CUBUAU2D.js → improvement-review-RKHKBKDU.js} +5 -5
- package/dist/index.d.ts +6 -2
- package/dist/index.js +31 -31
- package/dist/{init-opencode-4QECASK4.js → init-opencode-KTIHOYIU.js} +5 -5
- package/dist/issue-triage-OCTW33O3.js +16 -0
- package/dist/{pr-reviewer-helpers-RK5IT4US.js → pr-reviewer-helpers-V67TZHNM.js} +5 -5
- package/dist/{registry-command-MBZFFDWS.js → registry-command-43IZQOAP.js} +2 -2
- package/dist/{repo-security-plan-W76YLC2M.js → repo-security-plan-OXMSNBOS.js} +3 -3
- package/dist/{research-helpers-synthesize-GI5JFAQM.js → research-helpers-synthesize-IBBRMZEY.js} +4 -4
- package/dist/{routing-memory-WLCUOPDE.js → routing-memory-S3H3D6Z2.js} +2 -2
- package/dist/{session-memory-HU3XMQEH.js → session-memory-UO42CU2H.js} +3 -3
- package/dist/{setup-config-XA756R2O.js → setup-config-RGTKEVTD.js} +3 -3
- package/dist/{setup-custom-api-ETBGOE7O.js → setup-custom-api-PQ3PR2RR.js} +4 -4
- package/dist/setup-data-dir-AMMF6TWR.js +32 -0
- package/dist/{tool-memory-7XMQAQQM.js → tool-memory-ZMLCOQH6.js} +5 -5
- package/dist/{unified-registry-LR4OCUFI.js → unified-registry-HWBSGSOM.js} +10 -10
- package/dist/{weather-report-UYKQUSBB.js → weather-report-MZCA7Y6K.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-3PQIIMHN.js.map +0 -1
- package/dist/chunk-MS5VFQE3.js.map +0 -1
- package/dist/chunk-V76TXFRC.js.map +0 -1
- package/dist/issue-triage-BIEZBWV2.js +0 -16
- package/dist/setup-data-dir-XJWO2WOU.js +0 -32
- /package/dist/{ast-rule-runner-AMZCLKRV.js.map → ast-rule-runner-SD665GB7.js.map} +0 -0
- /package/dist/{child-mcp-config-7DSYI325.js.map → child-mcp-config-BG3QNALD.js.map} +0 -0
- /package/dist/{chunk-5UCGVAEZ.js.map → chunk-2N7XWZPW.js.map} +0 -0
- /package/dist/{chunk-BJXSG5YL.js.map → chunk-4KMNLWAC.js.map} +0 -0
- /package/dist/{chunk-QX42N7TE.js.map → chunk-4PMYNW3G.js.map} +0 -0
- /package/dist/{chunk-TLFZPJOY.js.map → chunk-C6Q2NUIH.js.map} +0 -0
- /package/dist/{chunk-EKZ6V7SE.js.map → chunk-FPX55ON5.js.map} +0 -0
- /package/dist/{chunk-KQE7EFBF.js.map → chunk-HBXAYO3C.js.map} +0 -0
- /package/dist/{chunk-JYKRCQSU.js.map → chunk-HD3FTCV4.js.map} +0 -0
- /package/dist/{chunk-AXBEG6VW.js.map → chunk-HPE3UQLT.js.map} +0 -0
- /package/dist/{chunk-UDWZJY3V.js.map → chunk-HUCILYVO.js.map} +0 -0
- /package/dist/{chunk-4IV25ZUM.js.map → chunk-IDASIJE6.js.map} +0 -0
- /package/dist/{chunk-MYZGLD7Y.js.map → chunk-J3HT4YDM.js.map} +0 -0
- /package/dist/{chunk-SCXCJSTT.js.map → chunk-JWHIFEI3.js.map} +0 -0
- /package/dist/{chunk-LZNYQYDU.js.map → chunk-KCWEMSU2.js.map} +0 -0
- /package/dist/{chunk-6FFBX665.js.map → chunk-NFP7WQ22.js.map} +0 -0
- /package/dist/{chunk-ILA4UGXI.js.map → chunk-NMZ5ZKEO.js.map} +0 -0
- /package/dist/{chunk-LFFXUHX3.js.map → chunk-O3MSZUQM.js.map} +0 -0
- /package/dist/{chunk-Z5VUMKF5.js.map → chunk-OJM75DDY.js.map} +0 -0
- /package/dist/{chunk-KSCQRZJZ.js.map → chunk-OX4L42RL.js.map} +0 -0
- /package/dist/{chunk-5GZ4UN5F.js.map → chunk-QCWY3GTZ.js.map} +0 -0
- /package/dist/{chunk-PENEGF75.js.map → chunk-RMDG3OFS.js.map} +0 -0
- /package/dist/{chunk-CG7OSI5P.js.map → chunk-S6FK47MZ.js.map} +0 -0
- /package/dist/{chunk-XU2SJKFK.js.map → chunk-SMKBETIX.js.map} +0 -0
- /package/dist/{chunk-ZTTBGME2.js.map → chunk-VI5TF3KF.js.map} +0 -0
- /package/dist/{chunk-JYZNPK62.js.map → chunk-VIDSDHSQ.js.map} +0 -0
- /package/dist/{chunk-3IBALX36.js.map → chunk-VLBXRQIA.js.map} +0 -0
- /package/dist/{chunk-TRCYUQ4M.js.map → chunk-WDGEJIWW.js.map} +0 -0
- /package/dist/{chunk-XJAGCUMD.js.map → chunk-ZP7LYABJ.js.map} +0 -0
- /package/dist/{chunk-VM4HZT3B.js.map → chunk-ZVHJMROO.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-MCQG3PQK.js.map → cli-circuit-breaker-GOH6U32K.js.map} +0 -0
- /package/dist/{composite-router-QAYCHEFG.js.map → composite-router-RMEHBA3J.js.map} +0 -0
- /package/dist/{consensus-vote-EIV5TDPY.js.map → consensus-vote-23XXJUDP.js.map} +0 -0
- /package/dist/{context-retriever-UXQCDDRY.js.map → context-retriever-TWAN22PW.js.map} +0 -0
- /package/dist/{doctor-deep-QRLRDFM4.js.map → doctor-deep-HRZ77NYS.js.map} +0 -0
- /package/dist/{doctor-live-CUKBQSSH.js.map → doctor-live-VGOABDSJ.js.map} +0 -0
- /package/dist/{expert-bridge-ZG2IA3RJ.js.map → expert-bridge-PFR7ZNWK.js.map} +0 -0
- /package/dist/{factory-FPNYFKXU.js.map → factory-DJPYG3WR.js.map} +0 -0
- /package/dist/{factory-RQEHJ4AW.js.map → factory-JCVKAI7P.js.map} +0 -0
- /package/dist/{improvement-review-CUBUAU2D.js.map → improvement-review-RKHKBKDU.js.map} +0 -0
- /package/dist/{init-opencode-4QECASK4.js.map → init-opencode-KTIHOYIU.js.map} +0 -0
- /package/dist/{issue-triage-BIEZBWV2.js.map → issue-triage-OCTW33O3.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-RK5IT4US.js.map → pr-reviewer-helpers-V67TZHNM.js.map} +0 -0
- /package/dist/{registry-command-MBZFFDWS.js.map → registry-command-43IZQOAP.js.map} +0 -0
- /package/dist/{repo-security-plan-W76YLC2M.js.map → repo-security-plan-OXMSNBOS.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-GI5JFAQM.js.map → research-helpers-synthesize-IBBRMZEY.js.map} +0 -0
- /package/dist/{routing-memory-WLCUOPDE.js.map → routing-memory-S3H3D6Z2.js.map} +0 -0
- /package/dist/{session-memory-HU3XMQEH.js.map → session-memory-UO42CU2H.js.map} +0 -0
- /package/dist/{setup-config-XA756R2O.js.map → setup-config-RGTKEVTD.js.map} +0 -0
- /package/dist/{setup-custom-api-ETBGOE7O.js.map → setup-custom-api-PQ3PR2RR.js.map} +0 -0
- /package/dist/{setup-data-dir-XJWO2WOU.js.map → setup-data-dir-AMMF6TWR.js.map} +0 -0
- /package/dist/{tool-memory-7XMQAQQM.js.map → tool-memory-ZMLCOQH6.js.map} +0 -0
- /package/dist/{unified-registry-LR4OCUFI.js.map → unified-registry-HWBSGSOM.js.map} +0 -0
- /package/dist/{weather-report-UYKQUSBB.js.map → weather-report-MZCA7Y6K.js.map} +0 -0
|
@@ -9,8 +9,8 @@ import {
|
|
|
9
9
|
getBuiltInAstRulesPath,
|
|
10
10
|
loadRules,
|
|
11
11
|
runAstQaRules
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-O3MSZUQM.js";
|
|
13
|
+
import "./chunk-F2H3MCEV.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-
|
|
29
|
+
//# sourceMappingURL=ast-rule-runner-SD665GB7.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-OITVVSWO.js";
|
|
4
4
|
import {
|
|
5
5
|
createLogger
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-F2H3MCEV.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-
|
|
59
|
+
//# sourceMappingURL=child-mcp-config-BG3QNALD.js.map
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GitHubProvider,
|
|
3
3
|
ScmError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JWHIFEI3.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveToken
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HUCILYVO.js";
|
|
8
8
|
import {
|
|
9
9
|
err,
|
|
10
10
|
ok
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-F2H3MCEV.js";
|
|
12
12
|
|
|
13
13
|
// src/scm/factory.ts
|
|
14
14
|
async function createScmProvider(config) {
|
|
@@ -41,4 +41,4 @@ export {
|
|
|
41
41
|
createScmProvider,
|
|
42
42
|
createGitHubProvider
|
|
43
43
|
};
|
|
44
|
-
//# sourceMappingURL=chunk-
|
|
44
|
+
//# sourceMappingURL=chunk-2N7XWZPW.js.map
|
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
planOptionalParams,
|
|
5
5
|
requireApiKey,
|
|
6
6
|
validateApiKeyPresence
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VI5TF3KF.js";
|
|
8
8
|
import {
|
|
9
9
|
assertCustomApiHostResolvesPublic,
|
|
10
10
|
hostnameOf,
|
|
11
11
|
redactApiKey
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KCWEMSU2.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-
|
|
34
|
+
} from "./chunk-F2H3MCEV.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-
|
|
889
|
+
//# sourceMappingURL=chunk-4KMNLWAC.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
2
|
import semver from "semver";
|
|
3
|
-
var VERSION = true ? "8.
|
|
3
|
+
var VERSION = true ? "8.90.0" : "dev";
|
|
4
4
|
var NODE_ENGINE_RANGE = ">=22.5.0";
|
|
5
5
|
function isNodeVersionSupported(version) {
|
|
6
6
|
return semver.satisfies(version, NODE_ENGINE_RANGE);
|
|
@@ -11,4 +11,4 @@ export {
|
|
|
11
11
|
NODE_ENGINE_RANGE,
|
|
12
12
|
isNodeVersionSupported
|
|
13
13
|
};
|
|
14
|
-
//# sourceMappingURL=chunk-
|
|
14
|
+
//# sourceMappingURL=chunk-4PMYNW3G.js.map
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
|
+
allOf,
|
|
3
|
+
verdictOver
|
|
4
|
+
} from "./chunk-EZNIYU5T.js";
|
|
5
|
+
import {
|
|
6
|
+
ApiArmIdSchema,
|
|
2
7
|
TASK_CATEGORIES,
|
|
3
8
|
getAdaptiveBonus,
|
|
4
|
-
getOutcomeStore
|
|
5
|
-
|
|
9
|
+
getOutcomeStore,
|
|
10
|
+
hasMeasuredCategory
|
|
11
|
+
} from "./chunk-F2H3MCEV.js";
|
|
6
12
|
|
|
7
13
|
// src/cli/doctor-deep.ts
|
|
8
14
|
var CLI_NAMES = ["claude", "gemini", "codex", "opencode"];
|
|
9
15
|
var COLD_START_THRESHOLD = 3;
|
|
16
|
+
var ROUTED_ARMS = [...CLI_NAMES, ...ApiArmIdSchema.options];
|
|
10
17
|
function checkLearningLoop() {
|
|
11
18
|
const store = getOutcomeStore();
|
|
12
19
|
const outcomes = store.query();
|
|
@@ -39,34 +46,50 @@ function checkDataSufficiency() {
|
|
|
39
46
|
const categoriesWithData = /* @__PURE__ */ new Set();
|
|
40
47
|
const allOutcomes = store.query();
|
|
41
48
|
for (const o of allOutcomes) {
|
|
42
|
-
categoriesWithData.add(o.category);
|
|
49
|
+
if (hasMeasuredCategory(o)) categoriesWithData.add(o.category);
|
|
43
50
|
}
|
|
44
51
|
const missing = TASK_CATEGORIES.filter((c) => !categoriesWithData.has(c));
|
|
45
52
|
return { cliStatus, missingCategories: missing, coldStartThreshold: COLD_START_THRESHOLD };
|
|
46
53
|
}
|
|
54
|
+
function roundRate(rate) {
|
|
55
|
+
return Math.round(rate * 1e3) / 1e3;
|
|
56
|
+
}
|
|
57
|
+
function tallyRowsByArm() {
|
|
58
|
+
const byArm = /* @__PURE__ */ new Map();
|
|
59
|
+
for (const o of getOutcomeStore().query()) {
|
|
60
|
+
if (!ROUTED_ARMS.includes(o.cli)) continue;
|
|
61
|
+
const tally = byArm.get(o.cli) ?? { total: 0, successes: 0 };
|
|
62
|
+
tally.total++;
|
|
63
|
+
if (o.success) tally.successes++;
|
|
64
|
+
byArm.set(o.cli, tally);
|
|
65
|
+
}
|
|
66
|
+
return byArm;
|
|
67
|
+
}
|
|
47
68
|
function checkConvergence() {
|
|
48
|
-
const
|
|
69
|
+
const rowsByArm = tallyRowsByArm();
|
|
70
|
+
const measured = [];
|
|
49
71
|
const rates = /* @__PURE__ */ new Map();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
rates.set(cli, Math.round(rate * 1e3) / 1e3);
|
|
56
|
-
totalRate += rate;
|
|
57
|
-
} else {
|
|
58
|
-
rates.set(cli, 0);
|
|
72
|
+
for (const arm of ROUTED_ARMS) {
|
|
73
|
+
const tally = rowsByArm.get(arm);
|
|
74
|
+
if (tally === void 0) {
|
|
75
|
+
rates.set(arm, { status: "unmeasured" });
|
|
76
|
+
continue;
|
|
59
77
|
}
|
|
78
|
+
const rate = tally.successes / tally.total;
|
|
79
|
+
measured.push({ rate, sampleCount: tally.total });
|
|
80
|
+
rates.set(arm, { status: "measured", rate: roundRate(rate), sampleCount: tally.total });
|
|
60
81
|
}
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
const avgSuccessRate = verdictOver(
|
|
83
|
+
measured,
|
|
84
|
+
(arms) => roundRate(arms.reduce((sum, a) => sum + a.rate, 0) / arms.length),
|
|
85
|
+
"unmeasured"
|
|
86
|
+
);
|
|
87
|
+
const converged = allOf(measured, (a) => a.sampleCount >= COLD_START_THRESHOLD, false);
|
|
66
88
|
return {
|
|
67
|
-
avgSuccessRate
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
avgSuccessRate,
|
|
90
|
+
armSuccessRates: rates,
|
|
91
|
+
measuredArmCount: measured.length,
|
|
92
|
+
converged
|
|
70
93
|
};
|
|
71
94
|
}
|
|
72
95
|
function runDeepDiagnostics() {
|
|
@@ -76,6 +99,23 @@ function runDeepDiagnostics() {
|
|
|
76
99
|
routingConvergence: checkConvergence()
|
|
77
100
|
};
|
|
78
101
|
}
|
|
102
|
+
function formatConvergenceRates(rc) {
|
|
103
|
+
const pct = (rate) => `${(rate * 100).toFixed(1)}%`;
|
|
104
|
+
if (rc.avgSuccessRate === "unmeasured") {
|
|
105
|
+
return [" Avg success rate: unmeasured (no arm has outcome rows)"];
|
|
106
|
+
}
|
|
107
|
+
const noun = rc.measuredArmCount === 1 ? "arm" : "arms";
|
|
108
|
+
const lines = [
|
|
109
|
+
` Avg success rate: ${pct(rc.avgSuccessRate)} over ${String(rc.measuredArmCount)} measured ${noun}`
|
|
110
|
+
];
|
|
111
|
+
const unmeasured = [];
|
|
112
|
+
for (const [arm, r] of rc.armSuccessRates) {
|
|
113
|
+
if (r.status === "unmeasured") unmeasured.push(arm);
|
|
114
|
+
else lines.push(` ${arm}: ${pct(r.rate)} (${String(r.sampleCount)} runs)`);
|
|
115
|
+
}
|
|
116
|
+
if (unmeasured.length > 0) lines.push(` Unmeasured (no rows): ${unmeasured.join(", ")}`);
|
|
117
|
+
return lines;
|
|
118
|
+
}
|
|
79
119
|
function formatDeepDiagnostics(diag) {
|
|
80
120
|
const lines = ["\n=== Deep Diagnostics ===\n"];
|
|
81
121
|
const ll = diag.learningLoop;
|
|
@@ -97,7 +137,7 @@ function formatDeepDiagnostics(diag) {
|
|
|
97
137
|
}
|
|
98
138
|
const rc = diag.routingConvergence;
|
|
99
139
|
lines.push("\nRouting Convergence:");
|
|
100
|
-
lines.push(
|
|
140
|
+
lines.push(...formatConvergenceRates(rc));
|
|
101
141
|
lines.push(` Converged: ${rc.converged ? "yes" : "no (still below cold-start threshold)"}`);
|
|
102
142
|
return lines.join("\n");
|
|
103
143
|
}
|
|
@@ -106,4 +146,4 @@ export {
|
|
|
106
146
|
runDeepDiagnostics,
|
|
107
147
|
formatDeepDiagnostics
|
|
108
148
|
};
|
|
109
|
-
//# sourceMappingURL=chunk-
|
|
149
|
+
//# sourceMappingURL=chunk-5GI6Z5VE.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 { hasMeasuredCategory } from '../orchestration/outcomes/outcome-types.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 // A defaulted category is not coverage of that category (#6549).\n if (hasMeasuredCategory(o)) 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":";;;;;;;;;;;;;AA0EA,IAAM,YAAY,CAAC,UAAU,UAAU,SAAS,UAAU;AAC1D,IAAM,uBAAuB;AAQ7B,IAAM,cAAiC,CAAC,GAAG,WAAW,GAAG,eAAe,OAAO;AAO/E,SAAS,oBAAwC;AAC/C,QAAM,QAAQ,gBAAgB;AAC9B,QAAM,WAAW,MAAM,MAAM;AAC7B,QAAM,kBACJ,SAAS,SAAS,IAAK,SAAS,SAAS,SAAS,CAAC,GAAG,aAAa,OAAQ;AAE7E,MAAI,gBAAgB;AACpB,QAAM,aAAa,UAAU,SAAS,gBAAgB;AACtD,aAAW,OAAO,WAAW;AAC3B,eAAW,OAAO,iBAAiB;AACjC,UAAI,iBAAiB,KAAK,GAAG,MAAM,EAAG;AAAA,IACxC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,eAAe,SAAS;AAAA,IACxB;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,EACnB;AACF;AAGA,SAAS,uBAAwC;AAC/C,QAAM,QAAQ,gBAAgB;AAC9B,QAAM,YAA6B,CAAC;AAEpC,aAAW,OAAO,WAAW;AAC3B,UAAM,WAAW,MAAM,MAAM,EAAE,IAAI,CAAC;AACpC,cAAU,KAAK;AAAA,MACb;AAAA,MACA,WAAW,SAAS;AAAA,MACpB,gBAAgB,SAAS,UAAU;AAAA,IACrC,CAAC;AAAA,EACH;AAEA,QAAM,qBAAqB,oBAAI,IAAkB;AACjD,QAAM,cAAc,MAAM,MAAM;AAChC,aAAW,KAAK,aAAa;AAE3B,QAAI,oBAAoB,CAAC,EAAG,oBAAmB,IAAI,EAAE,QAAQ;AAAA,EAC/D;AACA,QAAM,UAAU,gBAAgB,OAAO,CAAC,MAAM,CAAC,mBAAmB,IAAI,CAAC,CAAC;AAExE,SAAO,EAAE,WAAW,mBAAmB,SAAS,oBAAoB,qBAAqB;AAC3F;AAGA,SAAS,UAAU,MAAsB;AACvC,SAAO,KAAK,MAAM,OAAO,GAAI,IAAI;AACnC;AAQA,SAAS,iBAAoE;AAC3E,QAAM,QAAQ,oBAAI,IAAkD;AACpE,aAAW,KAAK,gBAAgB,EAAE,MAAM,GAAG;AACzC,QAAI,CAAC,YAAY,SAAS,EAAE,GAAG,EAAG;AAClC,UAAM,QAAQ,MAAM,IAAI,EAAE,GAAG,KAAK,EAAE,OAAO,GAAG,WAAW,EAAE;AAC3D,UAAM;AACN,QAAI,EAAE,QAAS,OAAM;AACrB,UAAM,IAAI,EAAE,KAAK,KAAK;AAAA,EACxB;AACA,SAAO;AACT;AASA,SAAS,mBAAuC;AAC9C,QAAM,YAAY,eAAe;AACjC,QAAM,WAA0B,CAAC;AACjC,QAAM,QAAQ,oBAAI,IAA4B;AAC9C,aAAW,OAAO,aAAa;AAC7B,UAAM,QAAQ,UAAU,IAAI,GAAG;AAC/B,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI,KAAK,EAAE,QAAQ,aAAa,CAAC;AACvC;AAAA,IACF;AACA,UAAM,OAAO,MAAM,YAAY,MAAM;AACrC,aAAS,KAAK,EAAE,MAAM,aAAa,MAAM,MAAM,CAAC;AAChD,UAAM,IAAI,KAAK,EAAE,QAAQ,YAAY,MAAM,UAAU,IAAI,GAAG,aAAa,MAAM,MAAM,CAAC;AAAA,EACxF;AAGA,QAAM,iBAAiB;AAAA,IACrB;AAAA,IACA,CAAC,SAAS,UAAU,KAAK,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM;AAAA,IAC1E;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,UAAU,CAAC,MAAM,EAAE,eAAe,sBAAsB,KAAK;AAErF,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB;AAAA,IACjB,kBAAkB,SAAS;AAAA,IAC3B;AAAA,EACF;AACF;AAOO,SAAS,qBAAsC;AACpD,SAAO;AAAA,IACL,cAAc,kBAAkB;AAAA,IAChC,iBAAiB,qBAAqB;AAAA,IACtC,oBAAoB,iBAAiB;AAAA,EACvC;AACF;AAGA,SAAS,uBAAuB,IAAkC;AAChE,QAAM,MAAM,CAAC,SAAyB,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC;AAChE,MAAI,GAAG,mBAAmB,cAAc;AACtC,WAAO,CAAC,0DAA0D;AAAA,EACpE;AACA,QAAM,OAAO,GAAG,qBAAqB,IAAI,QAAQ;AACjD,QAAM,QAAQ;AAAA,IACZ,uBAAuB,IAAI,GAAG,cAAc,CAAC,SAAS,OAAO,GAAG,gBAAgB,CAAC,aAAa,IAAI;AAAA,EACpG;AACA,QAAM,aAAuB,CAAC;AAC9B,aAAW,CAAC,KAAK,CAAC,KAAK,GAAG,iBAAiB;AACzC,QAAI,EAAE,WAAW,aAAc,YAAW,KAAK,GAAG;AAAA,QAC7C,OAAM,KAAK,OAAO,GAAG,KAAK,IAAI,EAAE,IAAI,CAAC,KAAK,OAAO,EAAE,WAAW,CAAC,QAAQ;AAAA,EAC9E;AACA,MAAI,WAAW,SAAS,EAAG,OAAM,KAAK,6BAA6B,WAAW,KAAK,IAAI,CAAC,EAAE;AAC1F,SAAO;AACT;AAGO,SAAS,sBAAsB,MAA+B;AACnE,QAAM,QAAkB,CAAC,8BAA8B;AAGvD,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,gBAAgB;AAC3B,QAAM,cAAc,GAAG,gBAAgB,IAAI,MAAM;AACjD,QAAM,KAAK,KAAK,WAAW,kBAAkB,OAAO,GAAG,aAAa,CAAC,UAAU;AAC/E,QAAM,YAAY,GAAG,gBAAgB,IAAI,MAAM;AAC/C,QAAM;AAAA,IACJ,KAAK,SAAS,sBAAsB,OAAO,GAAG,aAAa,CAAC,IAAI,OAAO,GAAG,eAAe,CAAC;AAAA,EAC5F;AAGA,QAAM,KAAK,qBAAqB;AAChC,aAAW,MAAM,KAAK,gBAAgB,WAAW;AAC/C,UAAM,OAAO,GAAG,iBAAiB,MAAM;AACvC,UAAM,QAAQ,GAAG,iBAAiB,oBAAoB;AACtD,UAAM,KAAK,KAAK,IAAI,IAAI,GAAG,GAAG,KAAK,OAAO,GAAG,SAAS,CAAC,WAAW,KAAK,GAAG;AAAA,EAC5E;AACA,MAAI,KAAK,gBAAgB,kBAAkB,SAAS,GAAG;AACrD,UAAM,KAAK,yBAAyB,KAAK,gBAAgB,kBAAkB,KAAK,IAAI,CAAC,EAAE;AAAA,EACzF;AAGA,QAAM,KAAK,KAAK;AAChB,QAAM,KAAK,wBAAwB;AACnC,QAAM,KAAK,GAAG,uBAAuB,EAAE,CAAC;AACxC,QAAM,KAAK,gBAAgB,GAAG,YAAY,QAAQ,uCAAuC,EAAE;AAE3F,SAAO,MAAM,KAAK,IAAI;AACxB;","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createAutoAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VIDSDHSQ.js";
|
|
4
4
|
import {
|
|
5
5
|
getDefaultCliCircuitBreakerRegistry,
|
|
6
6
|
mapModelErrorToCategory
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-SMKBETIX.js";
|
|
8
8
|
import {
|
|
9
9
|
CircularBuffer,
|
|
10
10
|
ConfigError,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
resolveModelIdentitySync,
|
|
29
29
|
toRateLimitError,
|
|
30
30
|
warnIfGatewayCostUndeclared
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-F2H3MCEV.js";
|
|
32
32
|
|
|
33
33
|
// src/config/model-equivalence.ts
|
|
34
34
|
function canonicalModelKey(modelId) {
|
|
@@ -975,4 +975,4 @@ export {
|
|
|
975
975
|
getGlobalRegistry,
|
|
976
976
|
resetGlobalRegistry
|
|
977
977
|
};
|
|
978
|
-
//# sourceMappingURL=chunk-
|
|
978
|
+
//# sourceMappingURL=chunk-C6Q2NUIH.js.map
|
|
@@ -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-
|
|
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":[]}
|
|
@@ -2696,7 +2696,7 @@ function setDefaultRegistry(registry) {
|
|
|
2696
2696
|
}
|
|
2697
2697
|
async function reloadDefaultRegistry() {
|
|
2698
2698
|
globalRegistry = buildDefaultRegistry();
|
|
2699
|
-
const { resetGlobalRegistry } = await import("./unified-registry-
|
|
2699
|
+
const { resetGlobalRegistry } = await import("./unified-registry-HWBSGSOM.js");
|
|
2700
2700
|
resetGlobalRegistry();
|
|
2701
2701
|
return globalRegistry;
|
|
2702
2702
|
}
|
|
@@ -10293,6 +10293,7 @@ var OutcomeFailureCategorySchema = z14.enum([
|
|
|
10293
10293
|
var OutcomeCliSchema = z14.union([CliNameSchema, ApiArmIdSchema, z14.literal("unknown")]);
|
|
10294
10294
|
var OutcomeCliSourceSchema = z14.enum(["executed", "category-default"]);
|
|
10295
10295
|
var OutcomeRoutedBySchema = z14.enum(["composite-router"]);
|
|
10296
|
+
var OutcomeCategorySourceSchema = z14.enum(["detected", "defaulted"]);
|
|
10296
10297
|
var TaskOutcomeSchema = z14.object({
|
|
10297
10298
|
id: z14.string().min(1),
|
|
10298
10299
|
cli: OutcomeCliSchema,
|
|
@@ -10301,6 +10302,8 @@ var TaskOutcomeSchema = z14.object({
|
|
|
10301
10302
|
/** Set only when `CompositeRouter` selected the CLI for this task (#6521). */
|
|
10302
10303
|
routedBy: OutcomeRoutedBySchema.optional(),
|
|
10303
10304
|
category: TaskCategorySchema,
|
|
10305
|
+
/** Whether `category` was detected or defaulted (#6549). Absent on legacy rows. */
|
|
10306
|
+
categorySource: OutcomeCategorySourceSchema.optional(),
|
|
10304
10307
|
model: z14.string().min(1),
|
|
10305
10308
|
success: z14.boolean(),
|
|
10306
10309
|
durationMs: z14.number().nonnegative(),
|
|
@@ -10357,6 +10360,16 @@ var OutcomeQuerySchema = z14.object({
|
|
|
10357
10360
|
/** Restrict to outcomes recorded against a specific baseline (#2697). */
|
|
10358
10361
|
baselineId: z14.string().min(1).max(64).optional()
|
|
10359
10362
|
});
|
|
10363
|
+
var UNDETECTED_CATEGORY_FALLBACK = "exploration";
|
|
10364
|
+
function resolveOutcomeCategory(detected) {
|
|
10365
|
+
if (detected === void 0) {
|
|
10366
|
+
return { category: UNDETECTED_CATEGORY_FALLBACK, categorySource: "defaulted" };
|
|
10367
|
+
}
|
|
10368
|
+
return { category: detected, categorySource: "detected" };
|
|
10369
|
+
}
|
|
10370
|
+
function hasMeasuredCategory(outcome) {
|
|
10371
|
+
return outcome.categorySource !== "defaulted";
|
|
10372
|
+
}
|
|
10360
10373
|
var TIMEOUT_PATTERNS = ["timeout", "timed out", "deadline exceeded", "socket hang up", "aborted"];
|
|
10361
10374
|
var AUTH_PATTERNS = [
|
|
10362
10375
|
"auth",
|
|
@@ -10561,6 +10574,7 @@ function isDistillerEligible(outcome) {
|
|
|
10561
10574
|
if (outcome.routedBy !== "composite-router") return false;
|
|
10562
10575
|
if (outcome.source === "consensus") return false;
|
|
10563
10576
|
if (!(outcome.durationMs > 0)) return false;
|
|
10577
|
+
if (!hasMeasuredCategory(outcome)) return false;
|
|
10564
10578
|
return ROUTABLE_CLIS.has(outcome.cli);
|
|
10565
10579
|
}
|
|
10566
10580
|
function countEligibleSince(outcomes, sinceMs) {
|
|
@@ -10579,7 +10593,8 @@ function getFileFieldsSchema() {
|
|
|
10579
10593
|
cli: true,
|
|
10580
10594
|
routedBy: true,
|
|
10581
10595
|
durationMs: true,
|
|
10582
|
-
timestamp: true
|
|
10596
|
+
timestamp: true,
|
|
10597
|
+
categorySource: true
|
|
10583
10598
|
});
|
|
10584
10599
|
return fileFieldsSchema;
|
|
10585
10600
|
}
|
|
@@ -11074,7 +11089,9 @@ var OutcomeStore = class {
|
|
|
11074
11089
|
successRate: successCount / outcomes.length,
|
|
11075
11090
|
avgDurationMs: totalDuration / outcomes.length,
|
|
11076
11091
|
byCli: groupBy(outcomes, (o) => o.cli),
|
|
11077
|
-
|
|
11092
|
+
// A defaulted category (#6549) is no category: totals count the row,
|
|
11093
|
+
// the per-category breakdown does not.
|
|
11094
|
+
byCategory: groupBy(outcomes.filter(hasMeasuredCategory), (o) => o.category)
|
|
11078
11095
|
};
|
|
11079
11096
|
}
|
|
11080
11097
|
/** Number of stored outcomes. */
|
|
@@ -11194,7 +11211,9 @@ ${failLines.join("\n")}` : "";
|
|
|
11194
11211
|
function buildPredicates(filter) {
|
|
11195
11212
|
const preds = [];
|
|
11196
11213
|
if (filter.cli !== void 0) preds.push((o) => o.cli === filter.cli);
|
|
11197
|
-
if (filter.category !== void 0)
|
|
11214
|
+
if (filter.category !== void 0) {
|
|
11215
|
+
preds.push((o) => hasMeasuredCategory(o) && o.category === filter.category);
|
|
11216
|
+
}
|
|
11198
11217
|
if (filter.source !== void 0) preds.push((o) => o.source === filter.source);
|
|
11199
11218
|
if (filter.success !== void 0) preds.push((o) => o.success === filter.success);
|
|
11200
11219
|
if (filter.failureCategory !== void 0) {
|
|
@@ -14111,7 +14130,7 @@ function buildCliWeather(summary, input) {
|
|
|
14111
14130
|
const cliOutcomes = store.query({ cli });
|
|
14112
14131
|
const byCategory = /* @__PURE__ */ new Map();
|
|
14113
14132
|
for (const cat of TASK_CATEGORIES) {
|
|
14114
|
-
const catOutcomes = cliOutcomes.filter((o) => o.category === cat);
|
|
14133
|
+
const catOutcomes = cliOutcomes.filter((o) => hasMeasuredCategory(o) && o.category === cat);
|
|
14115
14134
|
if (catOutcomes.length > 0) {
|
|
14116
14135
|
const sc = catOutcomes.filter((o) => o.success).length;
|
|
14117
14136
|
const td = catOutcomes.reduce((s, o) => s + o.durationMs, 0);
|
|
@@ -14276,7 +14295,9 @@ function buildSwarmHealth(expertPerf) {
|
|
|
14276
14295
|
let observedCategories = 0;
|
|
14277
14296
|
let analyzedCategories = 0;
|
|
14278
14297
|
for (const category of TASK_CATEGORIES) {
|
|
14279
|
-
const catOutcomes = allOutcomes.filter(
|
|
14298
|
+
const catOutcomes = allOutcomes.filter(
|
|
14299
|
+
(o) => hasMeasuredCategory(o) && o.category === category
|
|
14300
|
+
);
|
|
14280
14301
|
if (catOutcomes.length < ROUTING_MIN_SAMPLES) continue;
|
|
14281
14302
|
observedCategories++;
|
|
14282
14303
|
const stats = analyzeCategoryRouting(catOutcomes);
|
|
@@ -16100,7 +16121,7 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
16100
16121
|
*/
|
|
16101
16122
|
async consultUnifiedContext(task) {
|
|
16102
16123
|
try {
|
|
16103
|
-
const { getContextForTask, inferTaskCategory } = await import("./context-retriever-
|
|
16124
|
+
const { getContextForTask, inferTaskCategory } = await import("./context-retriever-TWAN22PW.js");
|
|
16104
16125
|
const ctx = await getContextForTask({
|
|
16105
16126
|
task: task.content,
|
|
16106
16127
|
category: inferTaskCategory(task.content),
|
|
@@ -17527,6 +17548,7 @@ export {
|
|
|
17527
17548
|
loadGeneratedRegistryEntries,
|
|
17528
17549
|
getFallbackChainForCategory,
|
|
17529
17550
|
isCliName,
|
|
17551
|
+
ApiArmIdSchema,
|
|
17530
17552
|
apiArmId,
|
|
17531
17553
|
routingArmDisplaySlot,
|
|
17532
17554
|
isEndpointArmId,
|
|
@@ -17582,6 +17604,8 @@ export {
|
|
|
17582
17604
|
validateTimeout,
|
|
17583
17605
|
OutcomeFailureCategorySchema,
|
|
17584
17606
|
TaskOutcomeSchema,
|
|
17607
|
+
resolveOutcomeCategory,
|
|
17608
|
+
hasMeasuredCategory,
|
|
17585
17609
|
extractNonErrorMessage,
|
|
17586
17610
|
categorizeOutcomeError,
|
|
17587
17611
|
categorizeOutcomeErrorMessage,
|
|
@@ -17758,4 +17782,4 @@ export {
|
|
|
17758
17782
|
AgentCapability,
|
|
17759
17783
|
OrchestratorError
|
|
17760
17784
|
};
|
|
17761
|
-
//# sourceMappingURL=chunk-
|
|
17785
|
+
//# sourceMappingURL=chunk-F2H3MCEV.js.map
|