nexus-agents 2.56.0 → 2.58.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/{adaptive-memory-SUNFPY2W.js → adaptive-memory-TSZEJUJC.js} +3 -3
- package/dist/{chunk-4FVISCDB.js → chunk-6QU4DJYW.js} +2 -2
- package/dist/{chunk-C3FGEDD7.js → chunk-7EYQBG3W.js} +22 -406
- package/dist/chunk-7EYQBG3W.js.map +1 -0
- package/dist/{chunk-NYNBDP7M.js → chunk-7Y36JLES.js} +2 -2
- package/dist/{chunk-FWSTXEG2.js → chunk-AFSIP6JH.js} +99 -23
- package/dist/chunk-AFSIP6JH.js.map +1 -0
- package/dist/{chunk-VKZKC4SM.js → chunk-EDGG3RQE.js} +2 -2
- package/dist/{chunk-2SPRLBOS.js → chunk-EZXOJZYE.js} +2 -2
- package/dist/{chunk-KGMC6F5D.js → chunk-GJ5BJU7A.js} +67 -61
- package/dist/chunk-GJ5BJU7A.js.map +1 -0
- package/dist/{chunk-W5AJRK4U.js → chunk-GMOGKX4E.js} +2 -2
- package/dist/chunk-H43PABG4.js +402 -0
- package/dist/chunk-H43PABG4.js.map +1 -0
- package/dist/{chunk-VLVHPC72.js → chunk-JKDHWOQL.js} +6 -6
- package/dist/{chunk-EJLWDYK7.js → chunk-JLYJQ7OG.js} +6159 -5619
- package/dist/chunk-JLYJQ7OG.js.map +1 -0
- package/dist/{chunk-IOU7F5PH.js → chunk-K7EA5OV4.js} +2 -2
- package/dist/{chunk-BPMQRYGU.js → chunk-L3NHOUEX.js} +332 -80
- package/dist/chunk-L3NHOUEX.js.map +1 -0
- package/dist/{chunk-KRIFBGWZ.js → chunk-PTGBJFSD.js} +3 -3
- package/dist/{chunk-EKYT4NMD.js → chunk-QGZBCD2A.js} +24 -9
- package/dist/chunk-QGZBCD2A.js.map +1 -0
- package/dist/{chunk-UOUJZIKH.js → chunk-R2Y57PM3.js} +38 -15
- package/dist/chunk-R2Y57PM3.js.map +1 -0
- package/dist/{chunk-PCMWLXT4.js → chunk-TC46TRLR.js} +2 -2
- package/dist/{chunk-3IDJSFWT.js → chunk-TFEFN37P.js} +2 -2
- package/dist/{chunk-Q5TKQWOI.js → chunk-V5CGWMYL.js} +2 -2
- package/dist/{chunk-TCQNNY4J.js → chunk-XEMRMZUN.js} +4 -4
- package/dist/{chunk-RSUCXOQM.js → chunk-YQAOMDR2.js} +26 -53
- package/dist/chunk-YQAOMDR2.js.map +1 -0
- package/dist/{chunk-R66AWJJ7.js → chunk-YU4NABXM.js} +2 -2
- package/dist/{cli-circuit-breaker-7MCMHSDY.js → cli-circuit-breaker-SL73NWX2.js} +4 -4
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +428 -342
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-LXFOSMSE.js → composite-router-A7URDW4X.js} +2 -2
- package/dist/{consensus-vote-G6H532ME.js → consensus-vote-HDM6HA5Z.js} +9 -8
- package/dist/{dist-4LDAFGC5.js → dist-RLMRWMYO.js} +994 -779
- package/dist/dist-RLMRWMYO.js.map +1 -0
- package/dist/{doctor-deep-RKMOZSIS.js → doctor-deep-VN6KMUCG.js} +3 -3
- package/dist/{expert-bridge-KHHE42JP.js → expert-bridge-BHTUNALT.js} +3 -3
- package/dist/{factory-JVN47MFN.js → factory-6MT5VKI3.js} +4 -4
- package/dist/{factory-KRNR7XHD.js → factory-FA7WDPZW.js} +5 -5
- package/dist/index.d.ts +396 -61
- package/dist/index.js +58 -43
- package/dist/index.js.map +1 -1
- package/dist/{issue-triage-O3C7P66H.js → issue-triage-YYTE6KTC.js} +4 -4
- package/dist/{mcp-config-QRERKGR4.js → mcp-config-34XMRM64.js} +3 -3
- package/dist/{mobimem-FAOAXV3B.js → mobimem-QDBP37H7.js} +2 -2
- package/dist/model-registry.generated.json +17033 -0
- package/dist/registry-command-S46JJ2SX.js +580 -0
- package/dist/registry-command-S46JJ2SX.js.map +1 -0
- package/dist/{repo-security-plan-AZ5HMGFC.js → repo-security-plan-C3LLE3Z7.js} +3 -3
- package/dist/{research-helpers-synthesize-E6WQLQKP.js → research-helpers-synthesize-NVQIWLQL.js} +3 -3
- package/dist/{routing-memory-MXF45FXT.js → routing-memory-W3YWMLJM.js} +2 -2
- package/dist/{session-memory-HL5XDBIL.js → session-memory-DWF5Z2LC.js} +3 -3
- package/dist/{setup-command-AV4MODEL.js → setup-command-KSQEYBDA.js} +8 -7
- package/dist/{setup-config-PWK6WHMG.js → setup-config-JA5IX53Q.js} +3 -3
- package/dist/{setup-custom-api-XAWKRDWV.js → setup-custom-api-CSB26HWD.js} +7 -5
- package/dist/setup-custom-api-CSB26HWD.js.map +1 -0
- package/dist/{weather-report-XZ5CENHE.js → weather-report-YQSLX4MS.js} +2 -2
- package/package.json +5 -5
- package/dist/chunk-BPMQRYGU.js.map +0 -1
- package/dist/chunk-C3FGEDD7.js.map +0 -1
- package/dist/chunk-EJLWDYK7.js.map +0 -1
- package/dist/chunk-EKYT4NMD.js.map +0 -1
- package/dist/chunk-FWSTXEG2.js.map +0 -1
- package/dist/chunk-KGMC6F5D.js.map +0 -1
- package/dist/chunk-RSUCXOQM.js.map +0 -1
- package/dist/chunk-UOUJZIKH.js.map +0 -1
- package/dist/dist-4LDAFGC5.js.map +0 -1
- package/dist/setup-custom-api-XAWKRDWV.js.map +0 -1
- /package/dist/{adaptive-memory-SUNFPY2W.js.map → adaptive-memory-TSZEJUJC.js.map} +0 -0
- /package/dist/{chunk-4FVISCDB.js.map → chunk-6QU4DJYW.js.map} +0 -0
- /package/dist/{chunk-NYNBDP7M.js.map → chunk-7Y36JLES.js.map} +0 -0
- /package/dist/{chunk-VKZKC4SM.js.map → chunk-EDGG3RQE.js.map} +0 -0
- /package/dist/{chunk-2SPRLBOS.js.map → chunk-EZXOJZYE.js.map} +0 -0
- /package/dist/{chunk-W5AJRK4U.js.map → chunk-GMOGKX4E.js.map} +0 -0
- /package/dist/{chunk-VLVHPC72.js.map → chunk-JKDHWOQL.js.map} +0 -0
- /package/dist/{chunk-IOU7F5PH.js.map → chunk-K7EA5OV4.js.map} +0 -0
- /package/dist/{chunk-KRIFBGWZ.js.map → chunk-PTGBJFSD.js.map} +0 -0
- /package/dist/{chunk-PCMWLXT4.js.map → chunk-TC46TRLR.js.map} +0 -0
- /package/dist/{chunk-3IDJSFWT.js.map → chunk-TFEFN37P.js.map} +0 -0
- /package/dist/{chunk-Q5TKQWOI.js.map → chunk-V5CGWMYL.js.map} +0 -0
- /package/dist/{chunk-TCQNNY4J.js.map → chunk-XEMRMZUN.js.map} +0 -0
- /package/dist/{chunk-R66AWJJ7.js.map → chunk-YU4NABXM.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-7MCMHSDY.js.map → cli-circuit-breaker-SL73NWX2.js.map} +0 -0
- /package/dist/{composite-router-LXFOSMSE.js.map → composite-router-A7URDW4X.js.map} +0 -0
- /package/dist/{consensus-vote-G6H532ME.js.map → consensus-vote-HDM6HA5Z.js.map} +0 -0
- /package/dist/{doctor-deep-RKMOZSIS.js.map → doctor-deep-VN6KMUCG.js.map} +0 -0
- /package/dist/{expert-bridge-KHHE42JP.js.map → expert-bridge-BHTUNALT.js.map} +0 -0
- /package/dist/{factory-JVN47MFN.js.map → factory-6MT5VKI3.js.map} +0 -0
- /package/dist/{factory-KRNR7XHD.js.map → factory-FA7WDPZW.js.map} +0 -0
- /package/dist/{issue-triage-O3C7P66H.js.map → issue-triage-YYTE6KTC.js.map} +0 -0
- /package/dist/{mcp-config-QRERKGR4.js.map → mcp-config-34XMRM64.js.map} +0 -0
- /package/dist/{mobimem-FAOAXV3B.js.map → mobimem-QDBP37H7.js.map} +0 -0
- /package/dist/{repo-security-plan-AZ5HMGFC.js.map → repo-security-plan-C3LLE3Z7.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-E6WQLQKP.js.map → research-helpers-synthesize-NVQIWLQL.js.map} +0 -0
- /package/dist/{routing-memory-MXF45FXT.js.map → routing-memory-W3YWMLJM.js.map} +0 -0
- /package/dist/{session-memory-HL5XDBIL.js.map → session-memory-DWF5Z2LC.js.map} +0 -0
- /package/dist/{setup-command-AV4MODEL.js.map → setup-command-KSQEYBDA.js.map} +0 -0
- /package/dist/{setup-config-PWK6WHMG.js.map → setup-config-JA5IX53Q.js.map} +0 -0
- /package/dist/{weather-report-XZ5CENHE.js.map → weather-report-YQSLX4MS.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
err,
|
|
4
4
|
getErrorMessage,
|
|
5
5
|
ok
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-R2Y57PM3.js";
|
|
7
7
|
|
|
8
8
|
// src/scm/types.ts
|
|
9
9
|
var ScmError = class extends Error {
|
|
@@ -243,4 +243,4 @@ export {
|
|
|
243
243
|
ScmError,
|
|
244
244
|
GitHubProvider
|
|
245
245
|
};
|
|
246
|
-
//# sourceMappingURL=chunk-
|
|
246
|
+
//# sourceMappingURL=chunk-K7EA5OV4.js.map
|
|
@@ -2,10 +2,13 @@ import {
|
|
|
2
2
|
CUSTOM_API_BASE_URL_ENV,
|
|
3
3
|
PROVIDER_ENV_KEYS,
|
|
4
4
|
validateCustomApiBaseUrl
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-YU4NABXM.js";
|
|
6
|
+
import {
|
|
7
|
+
CUSTOM_API_DEFAULT_MODEL
|
|
8
|
+
} from "./chunk-H43PABG4.js";
|
|
6
9
|
import {
|
|
7
10
|
SessionMemory
|
|
8
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-7Y36JLES.js";
|
|
9
12
|
import {
|
|
10
13
|
AdaptiveMemoryBackend,
|
|
11
14
|
HybridMemoryBackend,
|
|
@@ -14,7 +17,7 @@ import {
|
|
|
14
17
|
getMemoryEntry,
|
|
15
18
|
memoryExists,
|
|
16
19
|
memoryRowToEntry
|
|
17
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-TFEFN37P.js";
|
|
18
21
|
import {
|
|
19
22
|
stringifyValue,
|
|
20
23
|
tokenizeFiltered
|
|
@@ -26,7 +29,7 @@ import {
|
|
|
26
29
|
getAvailableClis,
|
|
27
30
|
isCliAvailable,
|
|
28
31
|
withTimeout
|
|
29
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-YQAOMDR2.js";
|
|
30
33
|
import {
|
|
31
34
|
AgentError,
|
|
32
35
|
CACHE_TIMEOUTS,
|
|
@@ -69,10 +72,11 @@ import {
|
|
|
69
72
|
ok,
|
|
70
73
|
recordRateLimitEvent,
|
|
71
74
|
registerPersistentOutcomeStoreFactory,
|
|
75
|
+
resolveCliAlias,
|
|
72
76
|
resolveVoteTimeout,
|
|
73
77
|
toRateLimitError,
|
|
74
78
|
validateTimeout
|
|
75
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-R2Y57PM3.js";
|
|
76
80
|
import {
|
|
77
81
|
OUTCOMES_FILE,
|
|
78
82
|
ensureLearningDir
|
|
@@ -866,6 +870,38 @@ function isToolDenied(toolName) {
|
|
|
866
870
|
return UNBYPASSABLE_TOOL_NAMES.includes(toolName);
|
|
867
871
|
}
|
|
868
872
|
|
|
873
|
+
// src/security/access-constraint-deriver/tool-risk.ts
|
|
874
|
+
var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
|
|
875
|
+
// Discovery / listing
|
|
876
|
+
"list_experts",
|
|
877
|
+
"list_workflows",
|
|
878
|
+
// Research reads
|
|
879
|
+
"research_query",
|
|
880
|
+
"research_analyze",
|
|
881
|
+
"research_catalog_review",
|
|
882
|
+
"research_synthesize",
|
|
883
|
+
// Memory reads
|
|
884
|
+
"memory_query",
|
|
885
|
+
"memory_stats",
|
|
886
|
+
// Observability
|
|
887
|
+
"weather_report",
|
|
888
|
+
"query_trace",
|
|
889
|
+
"query_task_state",
|
|
890
|
+
// Codebase intelligence (read-only over local files)
|
|
891
|
+
"search_codebase",
|
|
892
|
+
"extract_symbols",
|
|
893
|
+
// Repo analysis (read-only)
|
|
894
|
+
"repo_analyze",
|
|
895
|
+
"repo_security_plan",
|
|
896
|
+
// Routing recommendation (no side effects — returns recommendation)
|
|
897
|
+
"delegate_to_model",
|
|
898
|
+
// Registry import (returns a draft template — does not write)
|
|
899
|
+
"registry_import"
|
|
900
|
+
]);
|
|
901
|
+
function isRiskyTool(toolName) {
|
|
902
|
+
return !READ_ONLY_TOOLS2.has(toolName);
|
|
903
|
+
}
|
|
904
|
+
|
|
869
905
|
// src/security/access-constraint-deriver/enforcer.ts
|
|
870
906
|
function checkAccess(toolName, policy, args) {
|
|
871
907
|
if (isToolDenied(toolName)) {
|
|
@@ -884,12 +920,28 @@ function checkAccess(toolName, policy, args) {
|
|
|
884
920
|
}
|
|
885
921
|
if (policy.allowedTools === "*") return { decision: "allow" };
|
|
886
922
|
if (policy.allowedTools.includes(toolName)) return { decision: "allow" };
|
|
887
|
-
|
|
923
|
+
return decideOnViolation(toolName, policy.mode);
|
|
924
|
+
}
|
|
925
|
+
function decideOnViolation(toolName, mode) {
|
|
926
|
+
if (mode === "audit") {
|
|
888
927
|
return {
|
|
889
928
|
decision: "log-and-allow",
|
|
890
929
|
warning: `tool "${toolName}" not in derived policy (audit mode)`
|
|
891
930
|
};
|
|
892
931
|
}
|
|
932
|
+
if (mode === "confirm_risky") {
|
|
933
|
+
if (!isRiskyTool(toolName)) {
|
|
934
|
+
return {
|
|
935
|
+
decision: "log-and-allow",
|
|
936
|
+
warning: `tool "${toolName}" not in derived policy (confirm_risky mode, read-only \u2014 would have required human approval, allowed because read-only)`
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
return {
|
|
940
|
+
decision: "deny",
|
|
941
|
+
reason: `tool "${toolName}" not in derived policy (confirm_risky mode, risky \u2014 would have required human approval; denied for now, add to allowedTools or run in audit mode to allow)`,
|
|
942
|
+
matchedRule: "allowedTools:confirm_risky"
|
|
943
|
+
};
|
|
944
|
+
}
|
|
893
945
|
return {
|
|
894
946
|
decision: "deny",
|
|
895
947
|
reason: `tool "${toolName}" not in derived policy`,
|
|
@@ -1458,6 +1510,16 @@ function emitToolAudit(auditLogger, toolName, ctx, result, durationMs) {
|
|
|
1458
1510
|
durationMs
|
|
1459
1511
|
});
|
|
1460
1512
|
}
|
|
1513
|
+
function emitToolAuditException(auditLogger, toolName, ctx, durationMs) {
|
|
1514
|
+
const actor = actorFromContext(ctx);
|
|
1515
|
+
auditLogger.logToolInvocation({
|
|
1516
|
+
toolName,
|
|
1517
|
+
outcome: "error",
|
|
1518
|
+
actor,
|
|
1519
|
+
requestId: ctx.requestId,
|
|
1520
|
+
durationMs
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1461
1523
|
function emitPolicyAudit(auditLogger, toolName, ctx, reason) {
|
|
1462
1524
|
const actor = actorFromContext(ctx);
|
|
1463
1525
|
auditLogger.logPolicyDecision({
|
|
@@ -1551,31 +1613,42 @@ function createSecureHandler(handler, config) {
|
|
|
1551
1613
|
requestLogger
|
|
1552
1614
|
);
|
|
1553
1615
|
if (preCheckError) return preCheckError;
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1616
|
+
return executeAndAudit(handler, sanitizedArgs, requestContext, requestLogger, config);
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
async function executeAndAudit(handler, sanitizedArgs, requestContext, requestLogger, config) {
|
|
1620
|
+
const execStartTime = getTimeProvider().now();
|
|
1621
|
+
try {
|
|
1622
|
+
const result = await executeHandler(
|
|
1623
|
+
handler,
|
|
1624
|
+
sanitizedArgs,
|
|
1625
|
+
{ requestContext, logger: requestLogger },
|
|
1626
|
+
requestLogger
|
|
1627
|
+
);
|
|
1628
|
+
sanitizeToolResult(result, requestLogger);
|
|
1629
|
+
if (config.auditLogger) {
|
|
1630
|
+
emitToolAudit(
|
|
1631
|
+
config.auditLogger,
|
|
1632
|
+
config.toolName,
|
|
1633
|
+
requestContext,
|
|
1634
|
+
result,
|
|
1635
|
+
getTimeProvider().now() - execStartTime
|
|
1561
1636
|
);
|
|
1562
|
-
sanitizeToolResult(result, requestLogger);
|
|
1563
|
-
if (config.auditLogger) {
|
|
1564
|
-
emitToolAudit(
|
|
1565
|
-
config.auditLogger,
|
|
1566
|
-
config.toolName,
|
|
1567
|
-
requestContext,
|
|
1568
|
-
result,
|
|
1569
|
-
getTimeProvider().now() - execStartTime
|
|
1570
|
-
);
|
|
1571
|
-
}
|
|
1572
|
-
return result;
|
|
1573
|
-
} catch (error) {
|
|
1574
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1575
|
-
requestLogger.error("Tool execution failed", error instanceof Error ? error : void 0);
|
|
1576
|
-
return internalError(message, requestContext.requestId);
|
|
1577
1637
|
}
|
|
1578
|
-
|
|
1638
|
+
return result;
|
|
1639
|
+
} catch (error) {
|
|
1640
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1641
|
+
requestLogger.error("Tool execution failed", error instanceof Error ? error : void 0);
|
|
1642
|
+
if (config.auditLogger) {
|
|
1643
|
+
emitToolAuditException(
|
|
1644
|
+
config.auditLogger,
|
|
1645
|
+
config.toolName,
|
|
1646
|
+
requestContext,
|
|
1647
|
+
getTimeProvider().now() - execStartTime
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
return internalError(message, requestContext.requestId);
|
|
1651
|
+
}
|
|
1579
1652
|
}
|
|
1580
1653
|
|
|
1581
1654
|
// src/mcp/tools/tool-result.ts
|
|
@@ -1609,7 +1682,8 @@ var VOTER_ROLES = {
|
|
|
1609
1682
|
devex: "Developer Experience - evaluates usability, documentation, and developer workflow",
|
|
1610
1683
|
ai_ml: "AI/ML Engineer - evaluates AI/ML aspects, model selection, and learning capabilities",
|
|
1611
1684
|
pm: "Product Manager - evaluates business value, user impact, and resource allocation",
|
|
1612
|
-
catfish: "Contrarian Analyst - deliberately challenges proposals to prevent agreement bias (arXiv:2505.21503)"
|
|
1685
|
+
catfish: "Contrarian Analyst - deliberately challenges proposals to prevent agreement bias (arXiv:2505.21503)",
|
|
1686
|
+
scope_steward: "Scope Steward - asks whether to build at all; checks existing tools, biases toward kill-the-feature (#2185)"
|
|
1613
1687
|
};
|
|
1614
1688
|
|
|
1615
1689
|
// src/cli-adapters/cli-to-model-adapter.ts
|
|
@@ -2406,15 +2480,15 @@ async function collectStream(stream, options = {}) {
|
|
|
2406
2480
|
|
|
2407
2481
|
// src/adapters/claude-adapter-types.ts
|
|
2408
2482
|
var CLAUDE_MODELS = {
|
|
2409
|
-
OPUS_4: "claude-opus
|
|
2410
|
-
SONNET_4: "claude-sonnet
|
|
2411
|
-
HAIKU_4: "claude-haiku
|
|
2483
|
+
OPUS_4: getCliModelName("claude-opus"),
|
|
2484
|
+
SONNET_4: getCliModelName("claude-sonnet"),
|
|
2485
|
+
HAIKU_4: getCliModelName("claude-haiku")
|
|
2412
2486
|
};
|
|
2413
2487
|
var CLAUDE_MODEL_ALIASES = {
|
|
2414
2488
|
"claude-opus-4": CLAUDE_MODELS.OPUS_4,
|
|
2415
2489
|
"claude-sonnet-4": CLAUDE_MODELS.SONNET_4,
|
|
2416
2490
|
"claude-haiku-4": CLAUDE_MODELS.HAIKU_4,
|
|
2417
|
-
// Legacy alias
|
|
2491
|
+
// Legacy alias — pre-4.x users routed to the current haiku.
|
|
2418
2492
|
"claude-haiku-3": CLAUDE_MODELS.HAIKU_4
|
|
2419
2493
|
};
|
|
2420
2494
|
var DEFAULT_MAX_TOKENS = 4096;
|
|
@@ -2493,7 +2567,9 @@ function mapTool(tool) {
|
|
|
2493
2567
|
};
|
|
2494
2568
|
}
|
|
2495
2569
|
function resolveModelId(modelId) {
|
|
2496
|
-
|
|
2570
|
+
const registryId = resolveCliAlias(modelId);
|
|
2571
|
+
if (registryId !== void 0) return getCliModelName(registryId);
|
|
2572
|
+
return modelId;
|
|
2497
2573
|
}
|
|
2498
2574
|
function getModelCapabilities(modelId) {
|
|
2499
2575
|
const capabilities = [
|
|
@@ -3142,7 +3218,7 @@ function tryCustomOpenAiAdapter(logger11) {
|
|
|
3142
3218
|
if (customKey === void 0 || customBaseUrl === void 0 || customBaseUrl === "") {
|
|
3143
3219
|
return null;
|
|
3144
3220
|
}
|
|
3145
|
-
const customModelId = process.env["NEXUS_CUSTOM_MODEL"] ??
|
|
3221
|
+
const customModelId = process.env["NEXUS_CUSTOM_MODEL"] ?? CUSTOM_API_DEFAULT_MODEL;
|
|
3146
3222
|
logger11.info("Using custom-openai SDK adapter", {
|
|
3147
3223
|
model: customModelId,
|
|
3148
3224
|
baseUrl: customBaseUrl
|
|
@@ -3908,6 +3984,10 @@ var UnifiedAdapterRegistry = class {
|
|
|
3908
3984
|
// --------------------------------------------------------------------------
|
|
3909
3985
|
// Public API
|
|
3910
3986
|
// --------------------------------------------------------------------------
|
|
3987
|
+
/** Logger used by this registry. Exposed so singleton helpers can warn. */
|
|
3988
|
+
getLogger() {
|
|
3989
|
+
return this.logger;
|
|
3990
|
+
}
|
|
3911
3991
|
/**
|
|
3912
3992
|
* Get adapter for a task category. Uses pre-computed routing.
|
|
3913
3993
|
* Falls back to default adapter if category unknown.
|
|
@@ -3959,9 +4039,11 @@ var UnifiedAdapterRegistry = class {
|
|
|
3959
4039
|
* Falls back to default adapter if model not recognized.
|
|
3960
4040
|
*/
|
|
3961
4041
|
getAdapterForModel(modelPreference) {
|
|
3962
|
-
const
|
|
3963
|
-
(m) => m.id === modelPreference || m.cliAlias === modelPreference || m.cliModelName === modelPreference
|
|
4042
|
+
const exact = DEFAULT_MODEL_CAPABILITIES.models.find(
|
|
4043
|
+
(m) => m.id === modelPreference || m.cliAlias === modelPreference || m.cliModelName === modelPreference
|
|
3964
4044
|
);
|
|
4045
|
+
const prefix = exact ?? [...DEFAULT_MODEL_CAPABILITIES.models].filter((m) => modelPreference.startsWith(m.id)).sort((a, b) => b.id.length - a.id.length)[0];
|
|
4046
|
+
const model = prefix;
|
|
3965
4047
|
if (model !== void 0) {
|
|
3966
4048
|
this.logger.debug("Model resolved to CLI", {
|
|
3967
4049
|
model: modelPreference,
|
|
@@ -4064,12 +4146,44 @@ function createUnifiedRegistry(config) {
|
|
|
4064
4146
|
return new UnifiedAdapterRegistry(config);
|
|
4065
4147
|
}
|
|
4066
4148
|
function getGlobalRegistry(config) {
|
|
4067
|
-
globalRegistry
|
|
4149
|
+
if (globalRegistry === void 0) {
|
|
4150
|
+
globalRegistry = new UnifiedAdapterRegistry(config);
|
|
4151
|
+
return globalRegistry;
|
|
4152
|
+
}
|
|
4153
|
+
if (config !== void 0 && Object.keys(config).length > 0) {
|
|
4154
|
+
globalRegistry.getLogger().warn(
|
|
4155
|
+
"UnifiedAdapterRegistry singleton already initialized; provided config ignored. Call resetGlobalRegistry() first if reconfiguration is intentional.",
|
|
4156
|
+
{ providedKeys: Object.keys(config) }
|
|
4157
|
+
);
|
|
4158
|
+
}
|
|
4068
4159
|
return globalRegistry;
|
|
4069
4160
|
}
|
|
4070
4161
|
|
|
4071
4162
|
// src/cli/voter-prompts.ts
|
|
4072
4163
|
var DEFAULT_PROJECT = "nexus-agents";
|
|
4164
|
+
function prReviewModeAddendum() {
|
|
4165
|
+
return `
|
|
4166
|
+
PR-review mode \u2014 if you are reviewing a code diff (not a proposal) AND you have at least one concrete defect that justifies blocking the merge, populate the OPTIONAL TOP-LEVEL "findings" field on your JSON response. NOT inside reasoning \u2014 top-level. The schema:
|
|
4167
|
+
|
|
4168
|
+
"findings": [
|
|
4169
|
+
{
|
|
4170
|
+
"summary": "One-line summary",
|
|
4171
|
+
"location": "path/file.ext:LINE",
|
|
4172
|
+
"severity": "critical" | "high" | "medium" | "low",
|
|
4173
|
+
"gate": {
|
|
4174
|
+
"reread_cited_line": "passed",
|
|
4175
|
+
"traced_call_path": "passed",
|
|
4176
|
+
"named_assertion": "Concrete failing assertion \u2014 what test would fail and how. Substantive, not 'passed'.",
|
|
4177
|
+
"ruled_out_language_non_issue": "passed"
|
|
4178
|
+
},
|
|
4179
|
+
"claim": "What is wrong and why it justifies blocking."
|
|
4180
|
+
}
|
|
4181
|
+
]
|
|
4182
|
+
|
|
4183
|
+
A finding only triggers strict request_changes if all 4 gate fields = "passed" AND named_assertion is substantive (>10 chars naming a concrete failure, not just "passed"). Findings missing any of those surface as informational only \u2014 they do not block on their own. The 2026-04-25 audit (#2225) found a 100% false-positive rate when this gate wasn't enforced. If you're approving the diff, OMIT the findings field entirely. If reviewing a non-diff proposal, ignore this section.
|
|
4184
|
+
|
|
4185
|
+
History note: an earlier prompt asked for YAML inside reasoning; that format was lossy across JSON serialization (#2245). Use the top-level JSON array above.`;
|
|
4186
|
+
}
|
|
4073
4187
|
function voterFooter() {
|
|
4074
4188
|
return `
|
|
4075
4189
|
Workflow-test assessment (include in your reasoning):
|
|
@@ -4077,7 +4191,8 @@ Workflow-test assessment (include in your reasoning):
|
|
|
4077
4191
|
- Workflow integration: Does this fit existing CI/build/test pipelines?
|
|
4078
4192
|
- Incremental verifiability: Can progress be measured at each step?
|
|
4079
4193
|
|
|
4080
|
-
When rejecting, classify your reasons using categories: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE
|
|
4194
|
+
When rejecting, classify your reasons using categories: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE.
|
|
4195
|
+
${prReviewModeAddendum()}`;
|
|
4081
4196
|
}
|
|
4082
4197
|
function architectPrompt(project) {
|
|
4083
4198
|
return `You are a Software Architect voting on technical proposals for the ${project} project.
|
|
@@ -4170,7 +4285,67 @@ When rejecting, you MUST classify your reasons using categories: YAGNI, DRY_VIOL
|
|
|
4170
4285
|
IMPORTANT: Your job is to find legitimate concerns, not to reject everything.
|
|
4171
4286
|
If after genuine scrutiny you find no significant issues, you MAY approve.
|
|
4172
4287
|
But your default posture is skeptical \u2014 look for what others might miss.
|
|
4173
|
-
High-confidence rejections with specific reasoning are your most valuable output
|
|
4288
|
+
High-confidence rejections with specific reasoning are your most valuable output.
|
|
4289
|
+
${prReviewModeAddendum()}`;
|
|
4290
|
+
}
|
|
4291
|
+
function scopeStewardPrompt(project) {
|
|
4292
|
+
return `You are a Scope Steward voting on proposals for the ${project} project.
|
|
4293
|
+
|
|
4294
|
+
Your job is to gate against build-when-buy-would-do and feature sprawl.
|
|
4295
|
+
The originating case (2026-04-24): a 6-role panel approved building a USB flasher
|
|
4296
|
+
CLI without anyone flagging that Rufus already solves the problem better, for the
|
|
4297
|
+
same audience, with 100M+ installs of battle-tested code. This role exists to
|
|
4298
|
+
catch that class of mistake.
|
|
4299
|
+
|
|
4300
|
+
Your evaluation criteria \u2014 work through these mandatory checks in your reasoning:
|
|
4301
|
+
|
|
4302
|
+
1. **Existing-tool check.** Search your knowledge for tools, libraries, or
|
|
4303
|
+
services that already solve the stated problem. Name them concretely
|
|
4304
|
+
(not "there might be alternatives" \u2014 actual names: Rufus, ripgrep,
|
|
4305
|
+
esbuild, etc.). If you can't name an alternative, say so explicitly.
|
|
4306
|
+
|
|
4307
|
+
2. **Build-vs-buy math.** For each existing tool you named: what would we
|
|
4308
|
+
LOSE by adopting it (license, dependency surface, integration cost)?
|
|
4309
|
+
What would we GAIN by building our own (tighter integration, no extra
|
|
4310
|
+
binary, etc.)? Default lean: BUY. Building is justified only when the
|
|
4311
|
+
loss column is concrete and the gain column is load-bearing.
|
|
4312
|
+
|
|
4313
|
+
3. **Mission alignment.** Does this proposal serve the project's stated
|
|
4314
|
+
mission, or is it scope drift? If drift, name the drift specifically.
|
|
4315
|
+
|
|
4316
|
+
4. **Kill-the-feature option.** For every proposal, explicitly evaluate
|
|
4317
|
+
"what if we just didn't do this?" as a ranked option. Many proposals
|
|
4318
|
+
don't need to be built. Make the no-build case before the build case.
|
|
4319
|
+
|
|
4320
|
+
5. **Sprawl audit.** Check whether similar functionality already exists
|
|
4321
|
+
in the codebase. If it does, recommend extending \u2014 not forking. The
|
|
4322
|
+
anti-sprawl policy in CLAUDE.md is specifically the rule this role
|
|
4323
|
+
enforces.
|
|
4324
|
+
|
|
4325
|
+
Default bias: REJECT proposals where an existing tool fits, even if our
|
|
4326
|
+
own implementation would be marginally nicer. Only approve when the
|
|
4327
|
+
existing-tool check fails AND the kill-the-feature option is worse AND
|
|
4328
|
+
mission alignment is clear AND no comparable in-codebase functionality
|
|
4329
|
+
exists.
|
|
4330
|
+
|
|
4331
|
+
Few-shot example of a textbook rejection:
|
|
4332
|
+
> Proposal: "Add an aegis-boot subcommand to flash bootable USB sticks."
|
|
4333
|
+
> Steward response: "REJECT (DON'T-BUILD). Rufus has solved this for the
|
|
4334
|
+
> same audience for 10+ years with 100M+ installs and battle-tested code.
|
|
4335
|
+
> Adopting Rufus loses nothing material; building our own loses
|
|
4336
|
+
> maintenance bandwidth indefinitely. Mission alignment: aegis-boot's
|
|
4337
|
+
> mission is verifiable boot, not USB tooling. Kill option clearly wins.
|
|
4338
|
+
> No prior in-codebase functionality. Recommend: point users at Rufus in
|
|
4339
|
+
> the docs and stop here."
|
|
4340
|
+
|
|
4341
|
+
${voterFooter()}
|
|
4342
|
+
|
|
4343
|
+
When rejecting, you MUST classify reasons (YAGNI, DRY_VIOLATION,
|
|
4344
|
+
OVER_ENGINEERING, SCOPE_CREEP, MISALIGNED). The steward's most common
|
|
4345
|
+
categories are SCOPE_CREEP, YAGNI, and OVER_ENGINEERING.
|
|
4346
|
+
|
|
4347
|
+
You CAN approve. But your default posture is: "this should not be built;
|
|
4348
|
+
prove me wrong with the build-vs-buy math."`;
|
|
4174
4349
|
}
|
|
4175
4350
|
function getVoterPrompts(project = DEFAULT_PROJECT) {
|
|
4176
4351
|
return {
|
|
@@ -4179,7 +4354,8 @@ function getVoterPrompts(project = DEFAULT_PROJECT) {
|
|
|
4179
4354
|
devex: devexPrompt(project),
|
|
4180
4355
|
ai_ml: aiMlPrompt(project),
|
|
4181
4356
|
pm: pmPrompt(project),
|
|
4182
|
-
catfish: catfishPrompt(project)
|
|
4357
|
+
catfish: catfishPrompt(project),
|
|
4358
|
+
scope_steward: scopeStewardPrompt(project)
|
|
4183
4359
|
};
|
|
4184
4360
|
}
|
|
4185
4361
|
var VOTER_SYSTEM_PROMPTS = getVoterPrompts();
|
|
@@ -4189,7 +4365,8 @@ var SIMULATED_VOTE_REASONING = {
|
|
|
4189
4365
|
devex: "Assessed developer experience and workflow impact.",
|
|
4190
4366
|
ai_ml: "Analyzed AI/ML capabilities and learning potential.",
|
|
4191
4367
|
pm: "Evaluated business value and resource requirements.",
|
|
4192
|
-
catfish: "Challenged proposal assumptions and identified potential risks."
|
|
4368
|
+
catfish: "Challenged proposal assumptions and identified potential risks.",
|
|
4369
|
+
scope_steward: "Checked existing tools, build-vs-buy math, kill-the-feature option; bias toward not shipping."
|
|
4193
4370
|
};
|
|
4194
4371
|
|
|
4195
4372
|
// src/cli/voter-response.ts
|
|
@@ -4203,6 +4380,18 @@ var SyntheticVoteError = class extends Error {
|
|
|
4203
4380
|
this.name = "SyntheticVoteError";
|
|
4204
4381
|
}
|
|
4205
4382
|
};
|
|
4383
|
+
var RawFindingSchema = z2.object({
|
|
4384
|
+
summary: z2.string().min(1).max(500).describe("One-line summary of the issue"),
|
|
4385
|
+
location: z2.string().min(1).max(200).describe("path/file.ext:line"),
|
|
4386
|
+
severity: z2.enum(["critical", "high", "medium", "low"]).default("medium"),
|
|
4387
|
+
gate: z2.object({
|
|
4388
|
+
reread_cited_line: z2.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4389
|
+
traced_call_path: z2.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4390
|
+
named_assertion: z2.string().default("").describe("Concrete failing assertion \u2014 substantive, not a rubber-stamp word"),
|
|
4391
|
+
ruled_out_language_non_issue: z2.enum(["passed", "failed", "skipped"]).default("skipped")
|
|
4392
|
+
}),
|
|
4393
|
+
claim: z2.string().min(1).max(2e3).describe("What is wrong and why it justifies blocking")
|
|
4394
|
+
});
|
|
4206
4395
|
var VoteResponseSchema = z2.object({
|
|
4207
4396
|
decision: z2.enum(["approve", "reject", "abstain"]).describe("Your vote decision"),
|
|
4208
4397
|
reasoning: z2.string().min(10).max(4e3).describe("Explanation for your vote (10-4000 chars)"),
|
|
@@ -4219,8 +4408,48 @@ var VoteResponseSchema = z2.object({
|
|
|
4219
4408
|
"MISALIGNED",
|
|
4220
4409
|
"INSUFFICIENT_EVIDENCE"
|
|
4221
4410
|
])
|
|
4222
|
-
).optional().describe("Rejection reason categories when decision is reject")
|
|
4411
|
+
).optional().describe("Rejection reason categories when decision is reject"),
|
|
4412
|
+
/** Top-level structured findings for PR-review mode (#2245 v4 follow-up).
|
|
4413
|
+
* Replaces the YAML-in-reasoning encoding that proved lossy. */
|
|
4414
|
+
findings: z2.array(RawFindingSchema).optional().describe("Structured findings (PR review only)")
|
|
4223
4415
|
});
|
|
4416
|
+
var VOTE_PROMPT_EXAMPLES = `Example approve response:
|
|
4417
|
+
{
|
|
4418
|
+
"decision": "approve",
|
|
4419
|
+
"reasoning": "The proposal aligns with architectural patterns. Testability: high \u2014 unit tests can verify each component. Workflow integration: fits existing CI pipeline.",
|
|
4420
|
+
"confidence": 0.85,
|
|
4421
|
+
"conditions": ["Add unit tests before merge"]
|
|
4422
|
+
}
|
|
4423
|
+
|
|
4424
|
+
Example reject response:
|
|
4425
|
+
{
|
|
4426
|
+
"decision": "reject",
|
|
4427
|
+
"reasoning": "This adds speculative abstractions for hypothetical future needs. Testability: unclear \u2014 no concrete test plan provided.",
|
|
4428
|
+
"confidence": 0.80,
|
|
4429
|
+
"rejectionCategories": ["YAGNI", "OVER_ENGINEERING"]
|
|
4430
|
+
}
|
|
4431
|
+
|
|
4432
|
+
Example PR-review request_changes response with structured findings:
|
|
4433
|
+
{
|
|
4434
|
+
"decision": "reject",
|
|
4435
|
+
"reasoning": "Off-by-one in clampPageSize and missing null guard on response.timing \u2014 both visible in the diff.",
|
|
4436
|
+
"confidence": 0.9,
|
|
4437
|
+
"rejectionCategories": ["INSUFFICIENT_EVIDENCE"],
|
|
4438
|
+
"findings": [
|
|
4439
|
+
{
|
|
4440
|
+
"summary": "Off-by-one in clampPageSize",
|
|
4441
|
+
"location": "packages/nexus-agents/src/api/pagination.ts:18",
|
|
4442
|
+
"severity": "high",
|
|
4443
|
+
"gate": {
|
|
4444
|
+
"reread_cited_line": "passed",
|
|
4445
|
+
"traced_call_path": "passed",
|
|
4446
|
+
"named_assertion": "Test would assert clampPageSize(50, 100) === 50; this returns 49.",
|
|
4447
|
+
"ruled_out_language_non_issue": "passed"
|
|
4448
|
+
},
|
|
4449
|
+
"claim": "Function name says 'clamp to range' but returns requested-1 in the in-range path."
|
|
4450
|
+
}
|
|
4451
|
+
]
|
|
4452
|
+
}`;
|
|
4224
4453
|
function buildVotePrompt(proposal) {
|
|
4225
4454
|
return `Evaluate the following proposal and provide your vote.
|
|
4226
4455
|
|
|
@@ -4238,22 +4467,9 @@ Respond with a JSON object containing:
|
|
|
4238
4467
|
- confidence: Number between 0 and 1
|
|
4239
4468
|
- conditions: Optional array of conditions for approval
|
|
4240
4469
|
- rejectionCategories: Required when rejecting. Array of categories from: YAGNI, DRY_VIOLATION, OVER_ENGINEERING, SCOPE_CREEP, SECURITY_RISK, MISALIGNED, INSUFFICIENT_EVIDENCE
|
|
4470
|
+
- findings: PR-REVIEW MODE ONLY. Optional top-level array of structured findings \u2014 see "PR-review mode" in the system prompt. OMIT this field entirely when reviewing a non-diff proposal or when approving a diff.
|
|
4241
4471
|
|
|
4242
|
-
|
|
4243
|
-
{
|
|
4244
|
-
"decision": "approve",
|
|
4245
|
-
"reasoning": "The proposal aligns with architectural patterns. Testability: high \u2014 unit tests can verify each component. Workflow integration: fits existing CI pipeline.",
|
|
4246
|
-
"confidence": 0.85,
|
|
4247
|
-
"conditions": ["Add unit tests before merge"]
|
|
4248
|
-
}
|
|
4249
|
-
|
|
4250
|
-
Example reject response:
|
|
4251
|
-
{
|
|
4252
|
-
"decision": "reject",
|
|
4253
|
-
"reasoning": "This adds speculative abstractions for hypothetical future needs. Testability: unclear \u2014 no concrete test plan provided.",
|
|
4254
|
-
"confidence": 0.80,
|
|
4255
|
-
"rejectionCategories": ["YAGNI", "OVER_ENGINEERING"]
|
|
4256
|
-
}`;
|
|
4472
|
+
${VOTE_PROMPT_EXAMPLES}`;
|
|
4257
4473
|
}
|
|
4258
4474
|
function extractJsonFromResponse(text) {
|
|
4259
4475
|
const codeBlockMatch = /```(?:json)?\s*([\s\S]*?)```/i.exec(text);
|
|
@@ -4286,6 +4502,17 @@ function createFallbackVote(output, _role, reason) {
|
|
|
4286
4502
|
// Mark as synthetic
|
|
4287
4503
|
};
|
|
4288
4504
|
}
|
|
4505
|
+
function buildParsedVote(data) {
|
|
4506
|
+
return {
|
|
4507
|
+
decision: data.decision,
|
|
4508
|
+
reasoning: data.reasoning,
|
|
4509
|
+
confidence: data.confidence,
|
|
4510
|
+
...data.conditions !== void 0 ? { conditions: data.conditions } : {},
|
|
4511
|
+
...data.rejectionCategories !== void 0 ? { rejectionCategories: data.rejectionCategories } : {},
|
|
4512
|
+
...data.findings !== void 0 ? { findings: data.findings } : {},
|
|
4513
|
+
source: "parsed"
|
|
4514
|
+
};
|
|
4515
|
+
}
|
|
4289
4516
|
function parseVoteResponse(output, role, options) {
|
|
4290
4517
|
const allowSyntheticVote = options?.allowSyntheticVote ?? false;
|
|
4291
4518
|
try {
|
|
@@ -4293,15 +4520,7 @@ function parseVoteResponse(output, role, options) {
|
|
|
4293
4520
|
const parsed = JSON.parse(jsonStr);
|
|
4294
4521
|
const validated = VoteResponseSchema.safeParse(parsed);
|
|
4295
4522
|
if (validated.success) {
|
|
4296
|
-
return
|
|
4297
|
-
decision: validated.data.decision,
|
|
4298
|
-
reasoning: validated.data.reasoning,
|
|
4299
|
-
confidence: validated.data.confidence,
|
|
4300
|
-
...validated.data.conditions !== void 0 ? { conditions: validated.data.conditions } : {},
|
|
4301
|
-
...validated.data.rejectionCategories !== void 0 ? { rejectionCategories: validated.data.rejectionCategories } : {},
|
|
4302
|
-
source: "parsed"
|
|
4303
|
-
// Real vote from LLM
|
|
4304
|
-
};
|
|
4523
|
+
return buildParsedVote(validated.data);
|
|
4305
4524
|
}
|
|
4306
4525
|
const reason = `Validation failed: ${validated.error.issues.map((e) => e.message).join(", ")}`;
|
|
4307
4526
|
if (!allowSyntheticVote) {
|
|
@@ -4370,8 +4589,10 @@ var ROLE_VOTE_DISTRIBUTIONS = {
|
|
|
4370
4589
|
// Technical focus
|
|
4371
4590
|
pm: [55, 25, 20],
|
|
4372
4591
|
// Business focus - generally supportive
|
|
4373
|
-
catfish: [20, 65, 15]
|
|
4592
|
+
catfish: [20, 65, 15],
|
|
4374
4593
|
// Deliberately contrarian - challenges proposals (arXiv:2505.21503)
|
|
4594
|
+
scope_steward: [25, 60, 15]
|
|
4595
|
+
// Default-bias toward not shipping (#2185)
|
|
4375
4596
|
};
|
|
4376
4597
|
function selectWeightedDecision(weights) {
|
|
4377
4598
|
const random = getRandomProvider();
|
|
@@ -4422,7 +4643,12 @@ async function executeSingleVoteAttempt(role, proposal, adapter, timeoutMs) {
|
|
|
4422
4643
|
{ role: "system", content: VOTER_SYSTEM_PROMPTS[role] },
|
|
4423
4644
|
{ role: "user", content: buildVotePrompt(proposal) }
|
|
4424
4645
|
],
|
|
4425
|
-
|
|
4646
|
+
// 500 was correct for short proposal-style votes but caused mid-string
|
|
4647
|
+
// truncation ("Unterminated string in JSON at position N") in #2241 v3
|
|
4648
|
+
// when voters review code diffs — the JSON envelope + reasoning + YAML
|
|
4649
|
+
// findings block routinely exceed 500 tokens. Bumped to 2000 (#2245);
|
|
4650
|
+
// refine per use case if needed.
|
|
4651
|
+
maxTokens: 2e3,
|
|
4426
4652
|
temperature: 0.3
|
|
4427
4653
|
// Low temperature for consistent evaluations
|
|
4428
4654
|
};
|
|
@@ -4711,6 +4937,18 @@ var RejectionCategorySchema = z3.enum([
|
|
|
4711
4937
|
"INSUFFICIENT_EVIDENCE"
|
|
4712
4938
|
]);
|
|
4713
4939
|
var REJECTION_CATEGORIES = RejectionCategorySchema.options;
|
|
4940
|
+
var FindingShapeSchema = z3.object({
|
|
4941
|
+
summary: z3.string().min(1).max(500),
|
|
4942
|
+
location: z3.string().min(1).max(200),
|
|
4943
|
+
severity: z3.enum(["critical", "high", "medium", "low"]).default("medium"),
|
|
4944
|
+
gate: z3.object({
|
|
4945
|
+
reread_cited_line: z3.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4946
|
+
traced_call_path: z3.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4947
|
+
named_assertion: z3.string().default(""),
|
|
4948
|
+
ruled_out_language_non_issue: z3.enum(["passed", "failed", "skipped"]).default("skipped")
|
|
4949
|
+
}),
|
|
4950
|
+
claim: z3.string().min(1).max(2e3)
|
|
4951
|
+
});
|
|
4714
4952
|
var VoteSchema = z3.object({
|
|
4715
4953
|
decision: VoteDecisionSchema,
|
|
4716
4954
|
reasoning: z3.string().min(1).describe("Explanation for the vote"),
|
|
@@ -4718,6 +4956,9 @@ var VoteSchema = z3.object({
|
|
|
4718
4956
|
conditions: z3.array(z3.string()).optional().describe("Conditions for approval"),
|
|
4719
4957
|
/** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */
|
|
4720
4958
|
rejectionCategories: z3.array(RejectionCategorySchema).optional().describe("Rejection reason categories when decision is reject"),
|
|
4959
|
+
/** Pre-verified PR-review findings (#2245 v4 follow-up). Optional;
|
|
4960
|
+
* populated only when the voter emits the structured top-level array. */
|
|
4961
|
+
findings: z3.array(FindingShapeSchema).optional().describe("PR-review findings (pre-verified)"),
|
|
4721
4962
|
timestamp: z3.iso.datetime().optional()
|
|
4722
4963
|
});
|
|
4723
4964
|
var ProposalSchema = z3.object({
|
|
@@ -5940,11 +6181,21 @@ var ConsensusEngine = class {
|
|
|
5940
6181
|
ambiguityBand: this.quorumConfig.ambiguityBand
|
|
5941
6182
|
});
|
|
5942
6183
|
if (!ambiguous) return false;
|
|
5943
|
-
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
6184
|
+
let newVoters;
|
|
6185
|
+
try {
|
|
6186
|
+
newVoters = await this.voterExpansionCallback(
|
|
6187
|
+
proposalId,
|
|
6188
|
+
required.length,
|
|
6189
|
+
this.quorumConfig.votersPerExpansion
|
|
6190
|
+
);
|
|
6191
|
+
} catch (err2) {
|
|
6192
|
+
const error = err2 instanceof Error ? err2 : new Error(String(err2));
|
|
6193
|
+
this.logger.warn("Incremental quorum: expansion callback threw; closing as-is", {
|
|
6194
|
+
proposalId,
|
|
6195
|
+
errorMessage: error.message
|
|
6196
|
+
});
|
|
6197
|
+
return false;
|
|
6198
|
+
}
|
|
5948
6199
|
if (newVoters.length === 0) {
|
|
5949
6200
|
this.logger.info("Incremental quorum: no additional voters available", { proposalId });
|
|
5950
6201
|
return false;
|
|
@@ -12478,7 +12729,7 @@ function strategyToAlgorithm(strategy) {
|
|
|
12478
12729
|
return strategy;
|
|
12479
12730
|
}
|
|
12480
12731
|
function getVoterRoles(quickMode) {
|
|
12481
|
-
return quickMode ? ["architect", "security", "
|
|
12732
|
+
return quickMode ? ["architect", "security", "scope_steward"] : ["architect", "security", "devex", "ai_ml", "pm", "catfish", "scope_steward"];
|
|
12482
12733
|
}
|
|
12483
12734
|
function createEmptyConsensusResult(proposal, algorithm) {
|
|
12484
12735
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -12604,7 +12855,7 @@ async function processVotesWithCascade(votes, opts) {
|
|
|
12604
12855
|
var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
|
|
12605
12856
|
async function runContrarianCheck(proposal, log) {
|
|
12606
12857
|
try {
|
|
12607
|
-
const { executeExpert } = await import("./expert-bridge-
|
|
12858
|
+
const { executeExpert } = await import("./expert-bridge-BHTUNALT.js");
|
|
12608
12859
|
const prompt = [
|
|
12609
12860
|
"You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
|
|
12610
12861
|
"Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
|
|
@@ -12812,10 +13063,10 @@ function registerConsensusVoteTool(server, deps) {
|
|
|
12812
13063
|
strategy: VotingStrategySchema.optional().describe(
|
|
12813
13064
|
"Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order"
|
|
12814
13065
|
),
|
|
12815
|
-
quickMode: z19.boolean().optional().default(false).describe("Use 3 agents instead of
|
|
13066
|
+
quickMode: z19.boolean().optional().default(false).describe("Use 3 agents instead of 7"),
|
|
12816
13067
|
simulateVotes: z19.boolean().optional().default(false).describe("Use simulated votes")
|
|
12817
13068
|
};
|
|
12818
|
-
const description = "Execute multi-model consensus voting on a proposal. Uses
|
|
13069
|
+
const description = "Execute multi-model consensus voting on a proposal. Uses 7 specialized agent roles (architect, security, devex, ai_ml, pm, catfish, scope_steward) to vote on proposals with configurable strategies. Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514).";
|
|
12819
13070
|
const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {
|
|
12820
13071
|
toolName: "consensus_vote",
|
|
12821
13072
|
rateLimiter: deps.rateLimiter,
|
|
@@ -12895,6 +13146,7 @@ export {
|
|
|
12895
13146
|
createSecureHandler,
|
|
12896
13147
|
createMcpNotifier,
|
|
12897
13148
|
NOOP_NOTIFIER,
|
|
13149
|
+
abortSignalStorage,
|
|
12898
13150
|
withProgressHeartbeat,
|
|
12899
13151
|
withAccessPolicy,
|
|
12900
13152
|
getToolTimeout,
|
|
@@ -12976,4 +13228,4 @@ export {
|
|
|
12976
13228
|
CONSENSUS_VOTE_OUTPUT_SCHEMA,
|
|
12977
13229
|
registerConsensusVoteTool
|
|
12978
13230
|
};
|
|
12979
|
-
//# sourceMappingURL=chunk-
|
|
13231
|
+
//# sourceMappingURL=chunk-L3NHOUEX.js.map
|