nexus-agents 4.22.1 → 4.22.3
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/{child-mcp-config-GNF2DS7K.js → child-mcp-config-Y3QSDCYI.js} +2 -2
- package/dist/{chunk-IDLQNS5U.js → chunk-2SVIHHNJ.js} +3 -3
- package/dist/{chunk-MDVHI3PP.js → chunk-6U3LS57H.js} +6 -6
- package/dist/{chunk-26VBDXT7.js → chunk-7HBTESFT.js} +13 -7
- package/dist/chunk-7HBTESFT.js.map +1 -0
- package/dist/{chunk-CQ77TF4Y.js → chunk-BYUVLVN7.js} +1 -1
- package/dist/{chunk-CQ77TF4Y.js.map → chunk-BYUVLVN7.js.map} +1 -1
- package/dist/{chunk-TV3L3GME.js → chunk-CBORIR4Y.js} +2 -2
- package/dist/{chunk-JJC5YKBH.js → chunk-D6ZTSN34.js} +3 -3
- package/dist/{chunk-6MVRXQ6V.js → chunk-DGLAEH7Y.js} +2 -2
- package/dist/{chunk-HVCYICUX.js → chunk-EU7S5CDW.js} +35 -24
- package/dist/chunk-EU7S5CDW.js.map +1 -0
- package/dist/{chunk-QWTDGESS.js → chunk-FVUQY73A.js} +2 -2
- package/dist/{chunk-HWBUN7WP.js → chunk-GMJQ6QMZ.js} +2 -2
- package/dist/{chunk-S3EAMH4I.js → chunk-H7CV35LZ.js} +3 -3
- package/dist/{chunk-2SXZIUEA.js → chunk-ICGYXBS6.js} +2 -2
- package/dist/{chunk-3AAAEN6N.js → chunk-IK6JPHMX.js} +5 -5
- package/dist/{chunk-C67BIG35.js → chunk-JM42KPWJ.js} +8 -8
- package/dist/{chunk-3X2ZQAJI.js → chunk-JR4XD3T7.js} +4 -4
- package/dist/{chunk-BZTFS7FN.js → chunk-JV6SMJMJ.js} +2 -2
- package/dist/{chunk-Z6W6G35I.js → chunk-KDUSLLZM.js} +2 -2
- package/dist/{chunk-UTJRTD7H.js → chunk-LX5HF6N5.js} +134 -73
- package/dist/{chunk-UTJRTD7H.js.map → chunk-LX5HF6N5.js.map} +1 -1
- package/dist/{chunk-PT3QWCKF.js → chunk-MM7BINTV.js} +3 -3
- package/dist/{chunk-MNPD6TMW.js → chunk-MTGMOLRO.js} +2 -2
- package/dist/{chunk-CMXVOO4L.js → chunk-N5W3GATS.js} +7 -7
- package/dist/{chunk-7B5YTCHU.js → chunk-P422WQJM.js} +2 -2
- package/dist/{chunk-KASC5XK7.js → chunk-PSXX2GBZ.js} +7 -7
- package/dist/{chunk-VZHZFAYL.js → chunk-QRG7UR2F.js} +2 -2
- package/dist/{chunk-LYI5GXON.js → chunk-RE2GYZRK.js} +5 -5
- package/dist/{chunk-PAZLJC46.js → chunk-RMTTKP4L.js} +2 -2
- package/dist/{chunk-BDEWOJL4.js → chunk-SBLLJXJO.js} +2 -2
- package/dist/{chunk-ZDLWHEFZ.js → chunk-TBXAEAKP.js} +2 -2
- package/dist/{chunk-M4BAGHYQ.js → chunk-TMKBZG3W.js} +2 -2
- package/dist/{chunk-AQV5RKO7.js → chunk-V533P6BT.js} +4 -4
- package/dist/{chunk-G2USF7DN.js → chunk-W2DYH4WL.js} +8 -8
- package/dist/{chunk-NF7GW4QQ.js → chunk-X7MLVGJV.js} +2 -2
- package/dist/{chunk-AJM6RCCB.js → chunk-XYWCZNFC.js} +2 -2
- package/dist/{cli-circuit-breaker-NSXLDTKZ.js → cli-circuit-breaker-T2IKLJVA.js} +3 -3
- package/dist/cli.js +41 -43
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-ULSYJV7S.js → composite-router-CCDCVYTY.js} +2 -2
- package/dist/{consensus-vote-OUZGLMJ4.js → consensus-vote-TMMGZROW.js} +16 -16
- package/dist/{context-retriever-QAZWTGAT.js → context-retriever-CKJ7EJME.js} +8 -8
- package/dist/{doctor-deep-IWQUV5IH.js → doctor-deep-MIQ5QYUL.js} +3 -3
- package/dist/{doctor-live-MJSBAH5J.js → doctor-live-IAERE7DO.js} +9 -9
- package/dist/{expert-bridge-6D43UDLS.js → expert-bridge-5MK4DOB7.js} +4 -4
- package/dist/{factory-2MLMLJDK.js → factory-6FNJM6P3.js} +9 -9
- package/dist/{factory-GUBAT3HH.js → factory-OO7MN24L.js} +5 -5
- package/dist/{improvement-review-W6HJIQLG.js → improvement-review-DKCVIJSF.js} +5 -5
- package/dist/index.js +31 -31
- package/dist/{init-opencode-TCP3OSFK.js → init-opencode-CM2HL2PI.js} +6 -6
- package/dist/issue-triage-NH25YRNT.js +17 -0
- package/dist/{pr-reviewer-helpers-VKQR2T3Y.js → pr-reviewer-helpers-I5UIREUR.js} +5 -5
- package/dist/{registry-command-ALLKEWVO.js → registry-command-BYRGRQ3I.js} +2 -2
- package/dist/{repo-security-plan-SJYA5PJC.js → repo-security-plan-NP6AT3NR.js} +3 -3
- package/dist/{research-helpers-synthesize-ERZD3P4M.js → research-helpers-synthesize-2R6TO2SP.js} +4 -4
- package/dist/{routing-memory-4WAKAU2L.js → routing-memory-IZH3XQQH.js} +2 -2
- package/dist/{session-memory-XR5FJQSM.js → session-memory-OWEWA5BX.js} +3 -3
- package/dist/{setup-config-26GAKOC3.js → setup-config-O7LHHD42.js} +3 -3
- package/dist/{setup-custom-api-TKMWDJJW.js → setup-custom-api-OZ3QCQTJ.js} +4 -4
- package/dist/setup-data-dir-XPXP3KIZ.js +28 -0
- package/dist/{tool-memory-QCZKITSG.js → tool-memory-LYKMCW7U.js} +5 -5
- package/dist/{unified-registry-63G7RTA6.js → unified-registry-ZSPVJ4BO.js} +10 -10
- package/dist/{weather-report-JVVJXNQY.js → weather-report-4OFVK5Q5.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-26VBDXT7.js.map +0 -1
- package/dist/chunk-HVCYICUX.js.map +0 -1
- package/dist/issue-triage-CLHI2MHK.js +0 -17
- package/dist/setup-data-dir-BKIKRQCE.js +0 -28
- /package/dist/{child-mcp-config-GNF2DS7K.js.map → child-mcp-config-Y3QSDCYI.js.map} +0 -0
- /package/dist/{chunk-IDLQNS5U.js.map → chunk-2SVIHHNJ.js.map} +0 -0
- /package/dist/{chunk-MDVHI3PP.js.map → chunk-6U3LS57H.js.map} +0 -0
- /package/dist/{chunk-TV3L3GME.js.map → chunk-CBORIR4Y.js.map} +0 -0
- /package/dist/{chunk-JJC5YKBH.js.map → chunk-D6ZTSN34.js.map} +0 -0
- /package/dist/{chunk-6MVRXQ6V.js.map → chunk-DGLAEH7Y.js.map} +0 -0
- /package/dist/{chunk-QWTDGESS.js.map → chunk-FVUQY73A.js.map} +0 -0
- /package/dist/{chunk-HWBUN7WP.js.map → chunk-GMJQ6QMZ.js.map} +0 -0
- /package/dist/{chunk-S3EAMH4I.js.map → chunk-H7CV35LZ.js.map} +0 -0
- /package/dist/{chunk-2SXZIUEA.js.map → chunk-ICGYXBS6.js.map} +0 -0
- /package/dist/{chunk-3AAAEN6N.js.map → chunk-IK6JPHMX.js.map} +0 -0
- /package/dist/{chunk-C67BIG35.js.map → chunk-JM42KPWJ.js.map} +0 -0
- /package/dist/{chunk-3X2ZQAJI.js.map → chunk-JR4XD3T7.js.map} +0 -0
- /package/dist/{chunk-BZTFS7FN.js.map → chunk-JV6SMJMJ.js.map} +0 -0
- /package/dist/{chunk-Z6W6G35I.js.map → chunk-KDUSLLZM.js.map} +0 -0
- /package/dist/{chunk-PT3QWCKF.js.map → chunk-MM7BINTV.js.map} +0 -0
- /package/dist/{chunk-MNPD6TMW.js.map → chunk-MTGMOLRO.js.map} +0 -0
- /package/dist/{chunk-CMXVOO4L.js.map → chunk-N5W3GATS.js.map} +0 -0
- /package/dist/{chunk-7B5YTCHU.js.map → chunk-P422WQJM.js.map} +0 -0
- /package/dist/{chunk-KASC5XK7.js.map → chunk-PSXX2GBZ.js.map} +0 -0
- /package/dist/{chunk-VZHZFAYL.js.map → chunk-QRG7UR2F.js.map} +0 -0
- /package/dist/{chunk-LYI5GXON.js.map → chunk-RE2GYZRK.js.map} +0 -0
- /package/dist/{chunk-PAZLJC46.js.map → chunk-RMTTKP4L.js.map} +0 -0
- /package/dist/{chunk-BDEWOJL4.js.map → chunk-SBLLJXJO.js.map} +0 -0
- /package/dist/{chunk-ZDLWHEFZ.js.map → chunk-TBXAEAKP.js.map} +0 -0
- /package/dist/{chunk-M4BAGHYQ.js.map → chunk-TMKBZG3W.js.map} +0 -0
- /package/dist/{chunk-AQV5RKO7.js.map → chunk-V533P6BT.js.map} +0 -0
- /package/dist/{chunk-G2USF7DN.js.map → chunk-W2DYH4WL.js.map} +0 -0
- /package/dist/{chunk-NF7GW4QQ.js.map → chunk-X7MLVGJV.js.map} +0 -0
- /package/dist/{chunk-AJM6RCCB.js.map → chunk-XYWCZNFC.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-NSXLDTKZ.js.map → cli-circuit-breaker-T2IKLJVA.js.map} +0 -0
- /package/dist/{composite-router-ULSYJV7S.js.map → composite-router-CCDCVYTY.js.map} +0 -0
- /package/dist/{consensus-vote-OUZGLMJ4.js.map → consensus-vote-TMMGZROW.js.map} +0 -0
- /package/dist/{context-retriever-QAZWTGAT.js.map → context-retriever-CKJ7EJME.js.map} +0 -0
- /package/dist/{doctor-deep-IWQUV5IH.js.map → doctor-deep-MIQ5QYUL.js.map} +0 -0
- /package/dist/{doctor-live-MJSBAH5J.js.map → doctor-live-IAERE7DO.js.map} +0 -0
- /package/dist/{expert-bridge-6D43UDLS.js.map → expert-bridge-5MK4DOB7.js.map} +0 -0
- /package/dist/{factory-2MLMLJDK.js.map → factory-6FNJM6P3.js.map} +0 -0
- /package/dist/{factory-GUBAT3HH.js.map → factory-OO7MN24L.js.map} +0 -0
- /package/dist/{improvement-review-W6HJIQLG.js.map → improvement-review-DKCVIJSF.js.map} +0 -0
- /package/dist/{init-opencode-TCP3OSFK.js.map → init-opencode-CM2HL2PI.js.map} +0 -0
- /package/dist/{issue-triage-CLHI2MHK.js.map → issue-triage-NH25YRNT.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-VKQR2T3Y.js.map → pr-reviewer-helpers-I5UIREUR.js.map} +0 -0
- /package/dist/{registry-command-ALLKEWVO.js.map → registry-command-BYRGRQ3I.js.map} +0 -0
- /package/dist/{repo-security-plan-SJYA5PJC.js.map → repo-security-plan-NP6AT3NR.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-ERZD3P4M.js.map → research-helpers-synthesize-2R6TO2SP.js.map} +0 -0
- /package/dist/{routing-memory-4WAKAU2L.js.map → routing-memory-IZH3XQQH.js.map} +0 -0
- /package/dist/{session-memory-XR5FJQSM.js.map → session-memory-OWEWA5BX.js.map} +0 -0
- /package/dist/{setup-config-26GAKOC3.js.map → setup-config-O7LHHD42.js.map} +0 -0
- /package/dist/{setup-custom-api-TKMWDJJW.js.map → setup-custom-api-OZ3QCQTJ.js.map} +0 -0
- /package/dist/{setup-data-dir-BKIKRQCE.js.map → setup-data-dir-XPXP3KIZ.js.map} +0 -0
- /package/dist/{tool-memory-QCZKITSG.js.map → tool-memory-LYKMCW7U.js.map} +0 -0
- /package/dist/{unified-registry-63G7RTA6.js.map → unified-registry-ZSPVJ4BO.js.map} +0 -0
- /package/dist/{weather-report-JVVJXNQY.js.map → weather-report-4OFVK5Q5.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-RQV5ZUXT.js";
|
|
4
4
|
import {
|
|
5
5
|
createLogger
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
7
7
|
import "./chunk-HHLCAWAV.js";
|
|
8
8
|
import "./chunk-NBMWONHE.js";
|
|
9
9
|
import "./chunk-ZPWHCABL.js";
|
|
@@ -62,4 +62,4 @@ export {
|
|
|
62
62
|
generateMcpConfig,
|
|
63
63
|
getDefaultAllowedTools
|
|
64
64
|
};
|
|
65
|
-
//# sourceMappingURL=child-mcp-config-
|
|
65
|
+
//# sourceMappingURL=child-mcp-config-Y3QSDCYI.js.map
|
|
@@ -2623,7 +2623,7 @@ function setDefaultRegistry(registry) {
|
|
|
2623
2623
|
}
|
|
2624
2624
|
async function reloadDefaultRegistry() {
|
|
2625
2625
|
globalRegistry = buildDefaultRegistry();
|
|
2626
|
-
const { resetGlobalRegistry } = await import("./unified-registry-
|
|
2626
|
+
const { resetGlobalRegistry } = await import("./unified-registry-ZSPVJ4BO.js");
|
|
2627
2627
|
resetGlobalRegistry();
|
|
2628
2628
|
return globalRegistry;
|
|
2629
2629
|
}
|
|
@@ -15116,7 +15116,7 @@ var CompositeRouter = class _CompositeRouter {
|
|
|
15116
15116
|
*/
|
|
15117
15117
|
async consultUnifiedContext(task) {
|
|
15118
15118
|
try {
|
|
15119
|
-
const { getContextForTask, inferTaskCategory } = await import("./context-retriever-
|
|
15119
|
+
const { getContextForTask, inferTaskCategory } = await import("./context-retriever-CKJ7EJME.js");
|
|
15120
15120
|
const ctx = await getContextForTask({
|
|
15121
15121
|
task: task.content,
|
|
15122
15122
|
category: inferTaskCategory(task.content),
|
|
@@ -16709,4 +16709,4 @@ export {
|
|
|
16709
16709
|
AgentCapability,
|
|
16710
16710
|
OrchestratorError
|
|
16711
16711
|
};
|
|
16712
|
-
//# sourceMappingURL=chunk-
|
|
16712
|
+
//# sourceMappingURL=chunk-2SVIHHNJ.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GitHubProvider,
|
|
3
3
|
ScmError
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KDUSLLZM.js";
|
|
5
5
|
import {
|
|
6
6
|
ROLE_DEFAULT_TRUST,
|
|
7
7
|
ReputationCache,
|
|
@@ -11,20 +11,20 @@ import {
|
|
|
11
11
|
gateWithReputation,
|
|
12
12
|
resolveReputationGatingMode,
|
|
13
13
|
sanitizeInput
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-GMJQ6QMZ.js";
|
|
15
15
|
import {
|
|
16
16
|
emitPolicyEvent
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-X7MLVGJV.js";
|
|
18
18
|
import {
|
|
19
19
|
hasToken
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-XYWCZNFC.js";
|
|
21
21
|
import {
|
|
22
22
|
CLI_SUBPROCESS_TIMEOUTS,
|
|
23
23
|
createLogger,
|
|
24
24
|
err,
|
|
25
25
|
getTimeProvider,
|
|
26
26
|
ok
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
28
28
|
|
|
29
29
|
// src/security/trust-classifier.ts
|
|
30
30
|
function mapAuthorAssociation(association) {
|
|
@@ -1247,4 +1247,4 @@ export {
|
|
|
1247
1247
|
IssueTriage,
|
|
1248
1248
|
createIssueTriage
|
|
1249
1249
|
};
|
|
1250
|
-
//# sourceMappingURL=chunk-
|
|
1250
|
+
//# sourceMappingURL=chunk-6U3LS57H.js.map
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DECISION_EMOJI,
|
|
4
4
|
SEVERITY_EMOJI,
|
|
5
5
|
SEVERITY_ORDER2 as SEVERITY_ORDER
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BYUVLVN7.js";
|
|
7
7
|
import {
|
|
8
8
|
allOf
|
|
9
9
|
} from "./chunk-OQB3XC5O.js";
|
|
@@ -12,11 +12,11 @@ import {
|
|
|
12
12
|
gateWithReputation,
|
|
13
13
|
resolveReputationGatingMode,
|
|
14
14
|
sanitizeInput
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-GMJQ6QMZ.js";
|
|
16
16
|
import {
|
|
17
17
|
createLogger,
|
|
18
18
|
getTimeProvider
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
20
20
|
|
|
21
21
|
// src/dogfooding/pr-reviewer-helpers.ts
|
|
22
22
|
import { randomUUID } from "crypto";
|
|
@@ -149,12 +149,14 @@ function determineApproval(findings) {
|
|
|
149
149
|
return !hasBlocking;
|
|
150
150
|
}
|
|
151
151
|
function determineDecision(reviews, findings) {
|
|
152
|
+
const verdicts = reviews.filter((r) => r.errored !== true);
|
|
152
153
|
const hasCritical = findings.some((f) => f.severity === "critical");
|
|
153
154
|
const hasHigh = findings.some((f) => f.severity === "high");
|
|
154
|
-
const allApproved = allOf(
|
|
155
|
+
const allApproved = allOf(verdicts, (r) => r.approved, false);
|
|
155
156
|
if (hasCritical) return "request_changes";
|
|
156
157
|
if (hasHigh && !allApproved) return "request_changes";
|
|
157
158
|
if (findings.length > 0) return "comment";
|
|
159
|
+
if (verdicts.length === 0) return "comment";
|
|
158
160
|
return "approve";
|
|
159
161
|
}
|
|
160
162
|
function calculateConsensus(reviews) {
|
|
@@ -262,8 +264,12 @@ function createFailedReview(expertId, category, durationMs, error) {
|
|
|
262
264
|
return {
|
|
263
265
|
expertId,
|
|
264
266
|
expertType: category,
|
|
265
|
-
approved: true
|
|
266
|
-
//
|
|
267
|
+
// #5012: NOT `approved: true`. "Don't block on failures" made an expert
|
|
268
|
+
// that never ran indistinguishable from one that read the diff and had no
|
|
269
|
+
// objection, and `determineDecision` turned three of those into an APPROVE
|
|
270
|
+
// posted to GitHub.
|
|
271
|
+
approved: false,
|
|
272
|
+
errored: true,
|
|
267
273
|
summary: `Review failed: ${error}`,
|
|
268
274
|
findings: [],
|
|
269
275
|
durationMs,
|
|
@@ -291,4 +297,4 @@ export {
|
|
|
291
297
|
formatReviewComment,
|
|
292
298
|
createFailedReview
|
|
293
299
|
};
|
|
294
|
-
//# sourceMappingURL=chunk-
|
|
300
|
+
//# sourceMappingURL=chunk-7HBTESFT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dogfooding/pr-reviewer-helpers.ts"],"sourcesContent":["/**\n * nexus-agents/dogfooding - PR Reviewer Helpers\n *\n * Helper functions for PR review formatting and aggregation.\n *\n * @module dogfooding/pr-reviewer-helpers\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { Result } from '../core/index.js';\nimport { getTimeProvider, createLogger } from '../core/index.js';\nimport type { ScmUserMetadata } from '../scm/types.js';\nimport type {\n PRMetadata,\n PRReviewDraft,\n PRTrustAssessment,\n ExpertReviewResult,\n ReviewFinding,\n ReviewCategory,\n ReviewSeverity,\n ReviewDecision,\n} from './pr-review-types.js';\nimport {\n SEVERITY_ORDER,\n CATEGORY_DISPLAY_NAMES,\n SEVERITY_EMOJI,\n DECISION_EMOJI,\n} from './pr-review-types.js';\nimport { sanitizeInput } from '../security/input-sanitizer.js';\nimport { allOf } from '../utils/verdict-aggregation.js';\nimport {\n assessReputation,\n gateWithReputation,\n resolveReputationGatingMode,\n} from '../security/reputation-model.js';\nimport type {\n ReputationCache,\n ReputationGateDecision,\n ReputationAssessment,\n GitHubUserMetadata,\n} from '../security/reputation-model.js';\nimport type { ClassifyResult } from '../security/trust-classifier.js';\n\nconst repLogger = createLogger({ component: 'PRReviewer.reputation' });\n\n// =============================================================================\n// Reputation Gating Helpers (#3123, epic #3118 Phase 5)\n// =============================================================================\n\n/**\n * Best-effort account-age lookup for a PR author (#3133, Phase-3 equivalent for\n * the PR path). Returns the author's real account age in days via the provider's\n * `fetchUserMetadata`, or `undefined` on any failure (err Result, unparseable\n * `createdAt`, or an unexpected rejection) — never fabricated, never throws, so\n * the review is never blocked by this lookup.\n */\nexport async function fetchAccountAgeDays(\n provider: { fetchUserMetadata: (u: string) => Promise<Result<ScmUserMetadata, Error>> },\n username: string\n): Promise<number | undefined> {\n try {\n const result = await provider.fetchUserMetadata(username);\n if (!result.ok) return undefined;\n const createdMs = Date.parse(result.value.createdAt);\n if (!Number.isFinite(createdMs)) return undefined;\n return Math.floor((getTimeProvider().now() - createdMs) / 86_400_000);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Assesses the PR author's reputation from the signals available in the PR\n * event: author association + injection flags from the (sanitized) PR body, plus\n * the author's real account age when it was fetched (#3133). `accountAgeDays` is\n * OMITTED when the lookup failed — never fabricated, so the engine skips the\n * `new_account` signal. Returns undefined when reputation is disabled.\n */\nexport function assessPRReputation(\n pr: PRMetadata,\n cache: ReputationCache,\n enableReputation: boolean,\n accountAgeDays: number | undefined\n): ReputationAssessment | undefined {\n if (!enableReputation) return undefined;\n // Only `injectionFlags` is consumed here, and injection detection is\n // role-independent — the userRole arg ('unknown') and the sanitizer's own\n // trustTier output are intentionally irrelevant to this call.\n const sanitizeResult = sanitizeInput(pr.body, 'unknown', pr.author);\n const metadata: GitHubUserMetadata = {\n username: pr.author,\n ...(accountAgeDays !== undefined ? { accountAgeDays } : {}),\n authorAssociation: pr.authorAssociation,\n injectionFlags: sanitizeResult.injectionFlags,\n };\n return assessReputation(metadata, cache);\n}\n\n/** Builds the observability assessment surfaced on the review result (#3123). */\nexport function buildPRTrustAssessment(\n trustResult: ClassifyResult,\n reputation: ReputationAssessment | undefined,\n gateDecision: ReputationGateDecision\n): PRTrustAssessment {\n // Tier-1 (owner/allowlisted) authors cannot be suspicious.\n const isTier1 = trustResult.trustTier === '1';\n return {\n trustTier: trustResult.trustTier,\n userRole: trustResult.userRole,\n isAllowlisted: trustResult.isAllowlisted,\n reputationScore: reputation?.reputationScore,\n suspiciousSignals: isTier1 ? [] : (reputation?.suspiciousSignals ?? []),\n isSuspicious: isTier1 ? false : (reputation?.isSuspicious ?? false),\n enforcedTrustTier: gateDecision.enforcedTier,\n reputationReconciledTier: gateDecision.reconciledTier,\n gatingMode: gateDecision.mode,\n };\n}\n\n/**\n * Assesses the PR author's reputation and applies the gating rollout mode\n * (#3123). Returns the gate decision (for the policy gate) and the assessment\n * surfaced on the result. A suppressed demotion (audit/off) is logged.\n */\nexport function gatePRAuthor(\n pr: PRMetadata,\n trustResult: ClassifyResult,\n accountAgeDays: number | undefined,\n cache: ReputationCache,\n enableReputation: boolean\n): { gateDecision: ReputationGateDecision; trustAssessment: PRTrustAssessment } {\n const reputation = assessPRReputation(pr, cache, enableReputation, accountAgeDays);\n const gateDecision = gateWithReputation(\n trustResult.trustTier,\n reputation,\n resolveReputationGatingMode()\n );\n if (gateDecision.demotionSuppressed) {\n repLogger.warn('Reputation demotion suppressed by gating mode (would block under enforce)', {\n prNumber: pr.number,\n author: pr.author,\n mode: gateDecision.mode,\n classifierTier: trustResult.trustTier,\n reconciledTier: gateDecision.reconciledTier,\n });\n }\n return {\n gateDecision,\n trustAssessment: buildPRTrustAssessment(trustResult, reputation, gateDecision),\n };\n}\n\n// =============================================================================\n// Parsing Helpers\n// =============================================================================\n\nexport function parseSeverity(value: unknown): ReviewSeverity {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower in SEVERITY_ORDER) return lower as ReviewSeverity;\n }\n return 'medium';\n}\n\nexport function parseCategory(value: unknown): ReviewCategory {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower in CATEGORY_DISPLAY_NAMES) return lower as ReviewCategory;\n }\n return 'code_quality';\n}\n\nexport function extractSummary(output: Record<string, unknown>): string {\n if (typeof output.summary === 'string') return output.summary;\n if (typeof output.content === 'string') return output.content;\n if (typeof output.message === 'string') return output.message;\n return 'Review completed';\n}\n\nexport function extractStringField(\n record: Record<string, unknown>,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === 'string') return value;\n }\n return undefined;\n}\n\n// =============================================================================\n// Finding Parsing\n// =============================================================================\n\nexport function parseFindings(\n output: Record<string, unknown>,\n expertId: string,\n minSeverity: ReviewSeverity\n): ReviewFinding[] {\n const minOrder = SEVERITY_ORDER[minSeverity];\n const sources = collectSources(output);\n\n const findings: ReviewFinding[] = [];\n for (const source of sources) {\n if (!Array.isArray(source)) continue;\n for (const item of source) {\n const finding = parseOneFinding(item, expertId, minOrder);\n if (finding !== null) findings.push(finding);\n }\n }\n return findings;\n}\n\nfunction collectSources(output: Record<string, unknown>): unknown[] {\n return [\n output.findings,\n output.vulnerabilities,\n output.issues,\n (output as { content?: { findings?: unknown } }).content,\n ];\n}\n\nfunction parseOneFinding(item: unknown, expertId: string, minOrder: number): ReviewFinding | null {\n if (typeof item !== 'object' || item === null) return null;\n\n const record = item as Record<string, unknown>;\n const severity = parseSeverity(record.severity);\n if (SEVERITY_ORDER[severity] < minOrder) return null;\n\n return {\n id: randomUUID(),\n category: parseCategory(record.category),\n severity,\n title: extractStringField(record, 'title', 'name') ?? 'Finding',\n description: extractStringField(record, 'description', 'message') ?? '',\n file: typeof record.file === 'string' ? record.file : undefined,\n line: typeof record.line === 'number' ? record.line : undefined,\n suggestion: typeof record.suggestion === 'string' ? record.suggestion : undefined,\n expertId,\n confidence: typeof record.confidence === 'number' ? record.confidence : 0.7,\n };\n}\n\n// =============================================================================\n// Decision Helpers\n// =============================================================================\n\nexport function determineApproval(findings: ReviewFinding[]): boolean {\n const hasBlocking = findings.some((f) => f.severity === 'critical' || f.severity === 'high');\n return !hasBlocking;\n}\n\nexport function determineDecision(\n reviews: ExpertReviewResult[],\n findings: ReviewFinding[]\n): ReviewDecision {\n // #5012: an expert that errored produced no verdict, so it can neither\n // approve nor object. `allOf(reviews, …, false)` already refuses to call\n // ZERO reviews unanimous approval (#4581); feeding it synthetic approvals\n // for failed experts defeated that guard by making the list non-empty.\n const verdicts = reviews.filter((r) => r.errored !== true);\n const hasCritical = findings.some((f) => f.severity === 'critical');\n const hasHigh = findings.some((f) => f.severity === 'high');\n // Zero expert reviews is not unanimous approval (#4581): with `true` here the\n // `hasHigh && !allApproved` branch could never fire on an unreviewed PR, so a\n // HIGH finding silently downgraded from request_changes to comment.\n const allApproved = allOf(verdicts, (r) => r.approved, false);\n\n if (hasCritical) return 'request_changes';\n if (hasHigh && !allApproved) return 'request_changes';\n if (findings.length > 0) return 'comment';\n // Nothing read the diff, so there is nothing to approve. `comment` posts the\n // failure summaries without asserting the change is fine.\n if (verdicts.length === 0) return 'comment';\n return 'approve';\n}\n\nexport function calculateConsensus(reviews: ExpertReviewResult[]): number {\n if (reviews.length === 0) return 1;\n const approvals = reviews.filter((r) => r.approved).length;\n return approvals / reviews.length;\n}\n\n// =============================================================================\n// Counting Helpers\n// =============================================================================\n\nexport function countBySeverity(findings: ReviewFinding[]): Record<ReviewSeverity, number> {\n const counts: Record<ReviewSeverity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n for (const f of findings) {\n counts[f.severity]++;\n }\n\n return counts;\n}\n\nexport function countByCategory(findings: ReviewFinding[]): Record<ReviewCategory, number> {\n const counts: Record<ReviewCategory, number> = {\n security: 0,\n performance: 0,\n code_quality: 0,\n testing: 0,\n documentation: 0,\n architecture: 0,\n };\n\n for (const f of findings) {\n counts[f.category]++;\n }\n\n return counts;\n}\n\nexport function sumFindings(counts: Record<ReviewSeverity, number>): number {\n return Object.values(counts).reduce((a, b) => a + b, 0);\n}\n\n// =============================================================================\n// Summary Generation\n// =============================================================================\n\nexport function generateSummary(\n pr: PRMetadata,\n reviews: ExpertReviewResult[],\n decision: ReviewDecision\n): string {\n const expertSummaries = reviews\n .map((r) => `- **${CATEGORY_DISPLAY_NAMES[r.expertType as ReviewCategory]}**: ${r.summary}`)\n .join('\\n');\n\n return `Reviewed PR #${String(pr.number)}: ${pr.title}\n\n**Decision:** ${decision.replaceAll('_', ' ')}\n**Experts consulted:** ${String(reviews.length)}\n\n${expertSummaries}`;\n}\n\n// =============================================================================\n// GitHub Comment Formatting\n// =============================================================================\n\n/**\n * Formats the review result as a GitHub comment.\n */\nexport function formatReviewComment(result: PRReviewDraft): string {\n const emoji = DECISION_EMOJI[result.decision];\n const decisionText = result.decision.replaceAll('_', ' ').toUpperCase();\n\n const findingsSection = formatFindingsSection(result);\n const statsSection = formatStatsSection(result);\n\n return `## ${emoji} Nexus Agents Review: ${decisionText}\n\n${result.summary}\n\n${findingsSection}\n\n${statsSection}\n\n---\n*Reviewed by [nexus-agents](https://github.com/nexus-substrate/nexus-agents) in ${String(result.totalDurationMs)}ms*`;\n}\n\nfunction formatFindingsSection(result: PRReviewDraft): string {\n const allFindings = result.expertReviews.flatMap((r) => r.findings);\n\n if (allFindings.length === 0) {\n return '_No issues found._';\n }\n\n const sorted = [...allFindings].sort(\n (a, b) => SEVERITY_ORDER[b.severity] - SEVERITY_ORDER[a.severity]\n );\n\n const lines = ['### Findings', ''];\n\n for (const f of sorted) {\n const emoji = SEVERITY_EMOJI[f.severity];\n const loc =\n f.file !== undefined\n ? ` (\\`${f.file}${f.line !== undefined ? `:${String(f.line)}` : ''}\\`)`\n : '';\n lines.push(`${emoji} **${f.title}**${loc}`);\n lines.push(`> ${f.description}`);\n if (f.suggestion !== undefined) {\n lines.push(`> 💡 ${f.suggestion}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatStatsSection(result: PRReviewDraft): string {\n const { findingsBySeverity } = result;\n const total = sumFindings(findingsBySeverity);\n\n const parts: string[] = [];\n for (const severity of ['critical', 'high', 'medium', 'low', 'info'] as ReviewSeverity[]) {\n const count = findingsBySeverity[severity];\n if (count > 0) {\n parts.push(`${SEVERITY_EMOJI[severity]} ${String(count)} ${severity}`);\n }\n }\n\n return `<details>\n<summary>Review Statistics (${String(total)} findings)</summary>\n\n- Experts: ${String(result.expertCount)}\n- Consensus: ${(result.consensusScore * 100).toFixed(0)}%\n- Duration: ${String(result.totalDurationMs)}ms\n- Findings: ${parts.join(', ') || 'none'}\n\n</details>`;\n}\n\n// =============================================================================\n// Failed Review Factory\n// =============================================================================\n\nexport function createFailedReview(\n expertId: string,\n category: ReviewCategory,\n durationMs: number,\n error: string\n): ExpertReviewResult {\n return {\n expertId,\n expertType: category,\n // #5012: NOT `approved: true`. \"Don't block on failures\" made an expert\n // that never ran indistinguishable from one that read the diff and had no\n // objection, and `determineDecision` turned three of those into an APPROVE\n // posted to GitHub.\n approved: false,\n errored: true,\n summary: `Review failed: ${error}`,\n findings: [],\n durationMs,\n confidence: 0,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dogfooding/pr-review-types.ts","../src/security/sarif-types.ts"],"sourcesContent":["/**\n * nexus-agents/dogfooding - PR Review Types\n *\n * Type definitions for automated pull request review using\n * multi-agent collaboration.\n *\n * @module dogfooding/pr-review-types\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n */\n\nimport { z } from 'zod';\nimport type { FullCapableProvider } from '../scm/types.js';\nimport { FINDING_SEVERITY_LEVELS } from '../security/sarif-types.js';\n\n/**\n * Pull request file change information.\n */\nexport interface PRFileChange {\n /** File path */\n readonly filename: string;\n /** Change status */\n readonly status: 'added' | 'removed' | 'modified' | 'renamed' | 'copied';\n /** Number of additions */\n readonly additions: number;\n /** Number of deletions */\n readonly deletions: number;\n /** File patch/diff content */\n readonly patch?: string | undefined;\n /** Previous filename if renamed */\n readonly previousFilename?: string | undefined;\n}\n\n/**\n * Pull request metadata from GitHub API.\n */\nexport interface PRMetadata {\n /** PR number */\n readonly number: number;\n /** PR title */\n readonly title: string;\n /** PR description/body */\n readonly body: string;\n /** Author username */\n readonly author: string;\n /** GitHub API author_association (e.g., 'OWNER', 'COLLABORATOR', 'NONE') */\n readonly authorAssociation: string;\n /** Base branch */\n readonly base: string;\n /** Head branch */\n readonly head: string;\n /** Repository owner */\n readonly owner: string;\n /** Repository name */\n readonly repo: string;\n /** PR URL */\n readonly url: string;\n /** Whether PR is draft */\n readonly draft: boolean;\n /** PR labels */\n readonly labels: readonly string[];\n /** Changed files */\n readonly files: readonly PRFileChange[];\n /** Total additions */\n readonly additions: number;\n /** Total deletions */\n readonly deletions: number;\n /** Commit SHA of head */\n readonly headSha: string;\n}\n\n/**\n * Review severity levels.\n */\nexport type ReviewSeverity = (typeof FINDING_SEVERITY_LEVELS)[number];\n\n/**\n * Review category for organizing findings.\n */\nexport type ReviewCategory =\n 'security' | 'performance' | 'code_quality' | 'testing' | 'documentation' | 'architecture';\n\n/**\n * Individual review finding from an expert.\n */\nexport interface ReviewFinding {\n /** Unique finding ID */\n readonly id: string;\n /** Category of finding */\n readonly category: ReviewCategory;\n /** Severity level */\n readonly severity: ReviewSeverity;\n /** Finding title */\n readonly title: string;\n /** Detailed description */\n readonly description: string;\n /** Affected file (if applicable) */\n readonly file?: string | undefined;\n /** Line number (if applicable) */\n readonly line?: number | undefined;\n /** Suggested fix */\n readonly suggestion?: string | undefined;\n /** Expert that found this issue */\n readonly expertId: string;\n /** Confidence score (0-1) */\n readonly confidence: number;\n}\n\n/**\n * Review result from a single expert agent.\n */\nexport interface ExpertReviewResult {\n /** Expert ID */\n readonly expertId: string;\n /** Expert role/type */\n readonly expertType: string;\n /** Overall approval */\n readonly approved: boolean;\n /** Review summary */\n readonly summary: string;\n /** Individual findings */\n readonly findings: readonly ReviewFinding[];\n /** Execution time in ms */\n readonly durationMs: number;\n /** Confidence in review (0-1) */\n readonly confidence: number;\n}\n\n/**\n * Aggregated review decision after multi-agent debate.\n */\nexport type ReviewDecision = 'approve' | 'request_changes' | 'comment';\n\n/**\n * Complete PR review result from multi-agent collaboration.\n */\n/**\n * Trust + reputation assessment of the PR author, surfaced for observability\n * (#3123, epic #3118 Phase 5). Mirrors `issue_triage`'s assessment.\n */\nexport interface PRTrustAssessment {\n /** Classifier trust tier (1-4) from author association. */\n readonly trustTier: string;\n /** Author's GitHub role. */\n readonly userRole: string;\n /** Whether the author is on the maintainer allowlist. */\n readonly isAllowlisted: boolean;\n /** Reputation score (0-100) when reputation is enabled. */\n readonly reputationScore?: number | undefined;\n /** Suspicious signals detected (e.g. `new_account`, `injection_patterns_detected`). */\n readonly suspiciousSignals: readonly string[];\n /** Whether the author is flagged as suspicious. */\n readonly isSuspicious: boolean;\n /** Tier the policy gate ACTUALLY enforced (== trustTier under audit/off). */\n readonly enforcedTrustTier?: string | undefined;\n /** Tier reputation reconciliation computed — what enforce mode WOULD gate on. */\n readonly reputationReconciledTier?: string | undefined;\n /** Reputation-gating rollout mode applied: `off` | `audit` | `enforce`. */\n readonly gatingMode?: string | undefined;\n}\n\n/**\n * Result of fetching PR data plus best-effort author signals (#3133).\n */\nexport interface PRFetchData {\n readonly metadata: PRMetadata;\n readonly provider: FullCapableProvider;\n /** Author's real account age in days, when the lookup succeeded (#3133). */\n readonly accountAgeDays?: number;\n}\n\nexport interface PRReviewResult {\n /** Pull request number */\n readonly prNumber: number;\n /** Repository full name (owner/repo) */\n readonly repository: string;\n /** Overall decision */\n readonly decision: ReviewDecision;\n /** Executive summary */\n readonly summary: string;\n /** Individual expert reviews */\n readonly expertReviews: readonly ExpertReviewResult[];\n /** Aggregated findings by severity */\n readonly findingsBySeverity: Readonly<Record<ReviewSeverity, number>>;\n /** Aggregated findings by category */\n readonly findingsByCategory: Readonly<Record<ReviewCategory, number>>;\n /** Total execution time in ms */\n readonly totalDurationMs: number;\n /** Number of experts that participated */\n readonly expertCount: number;\n /**\n * Number of changed files the review covered (#4350).\n *\n * The demo command's progress line printed `expertReviews.length` under a\n * \"files\" label, so a 7-file PR reported \"3 files\" — the expert count. The\n * fetch was always correct; the result simply carried no file count to print.\n */\n readonly filesReviewed: number;\n /** Consensus score (0-1) */\n readonly consensusScore: number;\n /** Debate rounds completed */\n readonly debateRounds: number;\n /** Timestamp of review */\n readonly timestamp: string;\n /** Author trust + reputation assessment (#3123). */\n readonly trustAssessment: PRTrustAssessment;\n /**\n * What actually happened when the review was posted to GitHub (#4354).\n *\n * The review previously reported success whether or not the post landed: a\n * `createReview` rejection was logged and discarded, and a Rule-of-Two block\n * returned early, both leaving the CLI to print \"Review posted to GitHub.\"\n * over a review that does not exist. Callers must consult this rather than\n * inferring a successful post from a successful review.\n */\n readonly postOutcome: ReviewPostOutcome;\n}\n\n/**\n * A completed review before the posting step has run (#4354).\n *\n * Everything the reviewer aggregates is known before the post is attempted; the\n * outcome is stamped on afterwards. Keeping the two apart in the types is what\n * stops `postOutcome` from being defaulted to a hopeful value.\n */\nexport type PRReviewDraft = Omit<PRReviewResult, 'postOutcome'>;\n\n/** Terminal state of the GitHub review-posting step (#4354). */\nexport type ReviewPostOutcome =\n /** The review was created on GitHub. */\n | { readonly status: 'posted' }\n /** Posting was deliberately not attempted (dry-run, or a policy gate blocked it). */\n | { readonly status: 'skipped'; readonly reason: string }\n /** Posting was attempted and GitHub rejected it. */\n | { readonly status: 'failed'; readonly error: string };\n\n/**\n * Configuration for PR review.\n */\nexport interface PRReviewConfig {\n /** Experts to include in review */\n readonly experts: readonly ReviewCategory[];\n /** Maximum debate rounds */\n readonly maxDebateRounds: number;\n /** Consensus threshold (0-1) */\n readonly consensusThreshold: number;\n /** Minimum severity to report */\n readonly minSeverity: ReviewSeverity;\n /** Whether to post inline comments */\n readonly enableInlineComments: boolean;\n /** Whether to run in dry-run mode (no GitHub posting) */\n readonly dryRun: boolean;\n /** Whether to assess author reputation and gate on it (#3123). */\n readonly enableReputation: boolean;\n /** GitHub token for API access */\n readonly githubToken?: string | undefined;\n /** Model adapter configuration */\n readonly modelConfig?: {\n readonly temperature?: number;\n readonly maxTokens?: number;\n };\n}\n\n/**\n * Default PR review configuration.\n */\nexport const DEFAULT_PR_REVIEW_CONFIG: PRReviewConfig = {\n experts: ['security', 'code_quality', 'testing'],\n maxDebateRounds: 3,\n consensusThreshold: 0.7,\n minSeverity: 'low',\n enableInlineComments: true,\n dryRun: false,\n enableReputation: true,\n modelConfig: {\n temperature: 0.3,\n maxTokens: 8192,\n },\n};\n\n/**\n * Zod schema for PR review configuration.\n */\nexport const PRReviewConfigSchema = z.object({\n experts: z\n .array(\n z.enum([\n 'security',\n 'performance',\n 'code_quality',\n 'testing',\n 'documentation',\n 'architecture',\n ])\n )\n .default(['security', 'code_quality', 'testing']),\n maxDebateRounds: z.number().int().min(1).max(10).default(3),\n consensusThreshold: z.number().min(0).max(1).default(0.7),\n minSeverity: z.enum(FINDING_SEVERITY_LEVELS).default('low'),\n enableInlineComments: z.boolean().default(true),\n dryRun: z.boolean().default(false),\n enableReputation: z.boolean().default(true),\n githubToken: z.string().optional(),\n modelConfig: z\n .object({\n temperature: z.number().min(0).max(2).default(0.3),\n maxTokens: z.number().int().positive().default(8192),\n })\n .optional(),\n});\n\n/**\n * Severity order for comparison. INVERTED vs sarif-types' SEVERITY_ORDER by\n * design (higher = more severe here, for descending sort); only the KEY SET is\n * shared. Derived from the canonical {@link FINDING_SEVERITY_LEVELS} so the keys\n * can't drift (#3570): critical→5 … info→1.\n */\nexport const SEVERITY_ORDER: Record<ReviewSeverity, number> = Object.fromEntries(\n FINDING_SEVERITY_LEVELS.map((level, index) => [level, FINDING_SEVERITY_LEVELS.length - index])\n) as Record<ReviewSeverity, number>;\n\n/**\n * Category display names.\n */\nexport const CATEGORY_DISPLAY_NAMES: Record<ReviewCategory, string> = {\n security: 'Security',\n performance: 'Performance',\n code_quality: 'Code Quality',\n testing: 'Testing',\n documentation: 'Documentation',\n architecture: 'Architecture',\n};\n\n/**\n * Severity emoji for GitHub comments.\n */\nexport const SEVERITY_EMOJI: Record<ReviewSeverity, string> = {\n critical: ':rotating_light:',\n high: ':warning:',\n medium: ':yellow_circle:',\n low: ':large_blue_circle:',\n info: ':information_source:',\n};\n\n/**\n * Decision emoji for GitHub comments.\n */\nexport const DECISION_EMOJI: Record<ReviewDecision, string> = {\n approve: ':white_check_mark:',\n request_changes: ':x:',\n comment: ':speech_balloon:',\n};\n","/**\n * SARIF Types and Security Finding Schema (#1682)\n *\n * Types for parsing SARIF (Static Analysis Results Interchange Format)\n * output from security scanners (Semgrep, CodeQL, Bandit, ESLint).\n * Normalizes findings into a unified schema for MCP tool consumption.\n *\n * @module security/sarif-types\n * (Source: Issue #1681, #1682 — Proactive Defensive Security)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Unified Security Finding Schema\n// ============================================================================\n\n/**\n * Canonical 5-value finding-severity vocabulary (CVSS-aligned), most→least\n * severe. THE single source of truth — every 5-value finding-severity zod enum\n * (severity-consensus, finding-triage, agents/output-schemas, expert-types\n * VulnerabilitySeverity) and both SEVERITY_ORDER maps derive from this (#3570).\n * Tuple order is authoritative: SEVERITY_ORDER below maps it to ascending ranks.\n */\nexport const FINDING_SEVERITY_LEVELS = ['critical', 'high', 'medium', 'low', 'info'] as const;\n\n/** Severity levels aligned with CVSS and common scanner output. */\nexport const FindingSeveritySchema = z.enum(FINDING_SEVERITY_LEVELS);\nexport type FindingSeverity = z.infer<typeof FindingSeveritySchema>;\n\n/** A normalized security finding from any SARIF-compatible scanner. */\nexport const SecurityFindingSchema = z.object({\n /** Unique finding ID (scanner-specific rule ID). */\n id: z.string().min(1),\n /** Scanner that produced this finding. */\n scanner: z.string().min(1),\n /** Rule identifier (e.g., 'javascript.lang.security.detect-eval'). */\n rule: z.string().min(1),\n /** Normalized severity. */\n severity: FindingSeveritySchema,\n /** Human-readable description of the finding. */\n message: z.string().min(1).max(2000),\n /** File path where the finding was detected. */\n file: z.string().min(1),\n /** Start line number (1-based). */\n startLine: z.number().int().min(1),\n /** End line number (1-based, optional). */\n endLine: z.number().int().min(1).optional(),\n /** CWE identifiers (e.g., ['CWE-79', 'CWE-89']). */\n cweIds: z.array(z.string()).default([]),\n /** Scanner confidence (0-1). */\n confidence: z.number().min(0).max(1).default(0.5),\n /** Code snippet around the finding (optional). */\n snippet: z.string().max(500).optional(),\n /** Help URL for remediation guidance. */\n helpUrl: z.string().optional(),\n});\n\nexport type SecurityFinding = z.infer<typeof SecurityFindingSchema>;\n\n/** Result of parsing a SARIF file. */\nexport interface SarifParseResult {\n /** Scanner name extracted from SARIF. */\n readonly scanner: string;\n /** Total findings parsed. */\n readonly totalFindings: number;\n /** Findings sorted by severity (critical first). */\n readonly findings: readonly SecurityFinding[];\n /** Parsing errors (non-fatal). */\n readonly errors: readonly string[];\n}\n\n// ============================================================================\n// SARIF Input Types (subset of the SARIF 2.1.0 spec we need)\n// ============================================================================\n\n/** SARIF result level → our severity mapping. */\nexport const SARIF_LEVEL_MAP: Readonly<Record<string, FindingSeverity>> = {\n error: 'high',\n warning: 'medium',\n note: 'low',\n none: 'info',\n};\n\n/**\n * Severity order for sorting (lower = more severe). Derived from the canonical\n * tuple so it can never drift from {@link FINDING_SEVERITY_LEVELS} (#3570).\n */\nexport const SEVERITY_ORDER: Readonly<Record<FindingSeverity, number>> = Object.fromEntries(\n FINDING_SEVERITY_LEVELS.map((level, index) => [level, index])\n) as Record<FindingSeverity, number>;\n"],"mappings":"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","names":["z","z","SEVERITY_ORDER"]}
|
|
1
|
+
{"version":3,"sources":["../src/dogfooding/pr-review-types.ts","../src/security/sarif-types.ts"],"sourcesContent":["/**\n * nexus-agents/dogfooding - PR Review Types\n *\n * Type definitions for automated pull request review using\n * multi-agent collaboration.\n *\n * @module dogfooding/pr-review-types\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n */\n\nimport { z } from 'zod';\nimport type { FullCapableProvider } from '../scm/types.js';\nimport { FINDING_SEVERITY_LEVELS } from '../security/sarif-types.js';\n\n/**\n * Pull request file change information.\n */\nexport interface PRFileChange {\n /** File path */\n readonly filename: string;\n /** Change status */\n readonly status: 'added' | 'removed' | 'modified' | 'renamed' | 'copied';\n /** Number of additions */\n readonly additions: number;\n /** Number of deletions */\n readonly deletions: number;\n /** File patch/diff content */\n readonly patch?: string | undefined;\n /** Previous filename if renamed */\n readonly previousFilename?: string | undefined;\n}\n\n/**\n * Pull request metadata from GitHub API.\n */\nexport interface PRMetadata {\n /** PR number */\n readonly number: number;\n /** PR title */\n readonly title: string;\n /** PR description/body */\n readonly body: string;\n /** Author username */\n readonly author: string;\n /** GitHub API author_association (e.g., 'OWNER', 'COLLABORATOR', 'NONE') */\n readonly authorAssociation: string;\n /** Base branch */\n readonly base: string;\n /** Head branch */\n readonly head: string;\n /** Repository owner */\n readonly owner: string;\n /** Repository name */\n readonly repo: string;\n /** PR URL */\n readonly url: string;\n /** Whether PR is draft */\n readonly draft: boolean;\n /** PR labels */\n readonly labels: readonly string[];\n /** Changed files */\n readonly files: readonly PRFileChange[];\n /** Total additions */\n readonly additions: number;\n /** Total deletions */\n readonly deletions: number;\n /** Commit SHA of head */\n readonly headSha: string;\n}\n\n/**\n * Review severity levels.\n */\nexport type ReviewSeverity = (typeof FINDING_SEVERITY_LEVELS)[number];\n\n/**\n * Review category for organizing findings.\n */\nexport type ReviewCategory =\n 'security' | 'performance' | 'code_quality' | 'testing' | 'documentation' | 'architecture';\n\n/**\n * Individual review finding from an expert.\n */\nexport interface ReviewFinding {\n /** Unique finding ID */\n readonly id: string;\n /** Category of finding */\n readonly category: ReviewCategory;\n /** Severity level */\n readonly severity: ReviewSeverity;\n /** Finding title */\n readonly title: string;\n /** Detailed description */\n readonly description: string;\n /** Affected file (if applicable) */\n readonly file?: string | undefined;\n /** Line number (if applicable) */\n readonly line?: number | undefined;\n /** Suggested fix */\n readonly suggestion?: string | undefined;\n /** Expert that found this issue */\n readonly expertId: string;\n /** Confidence score (0-1) */\n readonly confidence: number;\n}\n\n/**\n * Review result from a single expert agent.\n */\nexport interface ExpertReviewResult {\n /** Expert ID */\n readonly expertId: string;\n /** Expert role/type */\n readonly expertType: string;\n /** Overall approval */\n readonly approved: boolean;\n /** Review summary */\n readonly summary: string;\n /** Individual findings */\n readonly findings: readonly ReviewFinding[];\n /** Execution time in ms */\n readonly durationMs: number;\n /** Confidence in review (0-1) */\n readonly confidence: number;\n /**\n * The expert never produced a verdict — its adapter failed or returned\n * nothing (#5012).\n *\n * `approved` cannot express this. A failed expert used to be recorded as\n * `approved: true` (\"don't block on failures\"), so a review in which every\n * expert failed resolved to `approve` at 100% consensus and was posted to\n * GitHub as a real APPROVE. Absence of a review is not approval — a consumer\n * must be able to tell them apart, and `confidence: 0` was already present\n * and already ignored.\n */\n readonly errored?: boolean;\n}\n\n/**\n * Aggregated review decision after multi-agent debate.\n */\nexport type ReviewDecision = 'approve' | 'request_changes' | 'comment';\n\n/**\n * Complete PR review result from multi-agent collaboration.\n */\n/**\n * Trust + reputation assessment of the PR author, surfaced for observability\n * (#3123, epic #3118 Phase 5). Mirrors `issue_triage`'s assessment.\n */\nexport interface PRTrustAssessment {\n /** Classifier trust tier (1-4) from author association. */\n readonly trustTier: string;\n /** Author's GitHub role. */\n readonly userRole: string;\n /** Whether the author is on the maintainer allowlist. */\n readonly isAllowlisted: boolean;\n /** Reputation score (0-100) when reputation is enabled. */\n readonly reputationScore?: number | undefined;\n /** Suspicious signals detected (e.g. `new_account`, `injection_patterns_detected`). */\n readonly suspiciousSignals: readonly string[];\n /** Whether the author is flagged as suspicious. */\n readonly isSuspicious: boolean;\n /** Tier the policy gate ACTUALLY enforced (== trustTier under audit/off). */\n readonly enforcedTrustTier?: string | undefined;\n /** Tier reputation reconciliation computed — what enforce mode WOULD gate on. */\n readonly reputationReconciledTier?: string | undefined;\n /** Reputation-gating rollout mode applied: `off` | `audit` | `enforce`. */\n readonly gatingMode?: string | undefined;\n}\n\n/**\n * Result of fetching PR data plus best-effort author signals (#3133).\n */\nexport interface PRFetchData {\n readonly metadata: PRMetadata;\n readonly provider: FullCapableProvider;\n /** Author's real account age in days, when the lookup succeeded (#3133). */\n readonly accountAgeDays?: number;\n}\n\nexport interface PRReviewResult {\n /** Pull request number */\n readonly prNumber: number;\n /** Repository full name (owner/repo) */\n readonly repository: string;\n /** Overall decision */\n readonly decision: ReviewDecision;\n /** Executive summary */\n readonly summary: string;\n /** Individual expert reviews */\n readonly expertReviews: readonly ExpertReviewResult[];\n /** Aggregated findings by severity */\n readonly findingsBySeverity: Readonly<Record<ReviewSeverity, number>>;\n /** Aggregated findings by category */\n readonly findingsByCategory: Readonly<Record<ReviewCategory, number>>;\n /** Total execution time in ms */\n readonly totalDurationMs: number;\n /** Number of experts that participated */\n readonly expertCount: number;\n /**\n * Number of changed files the review covered (#4350).\n *\n * The demo command's progress line printed `expertReviews.length` under a\n * \"files\" label, so a 7-file PR reported \"3 files\" — the expert count. The\n * fetch was always correct; the result simply carried no file count to print.\n */\n readonly filesReviewed: number;\n /** Consensus score (0-1) */\n readonly consensusScore: number;\n /** Debate rounds completed */\n readonly debateRounds: number;\n /** Timestamp of review */\n readonly timestamp: string;\n /** Author trust + reputation assessment (#3123). */\n readonly trustAssessment: PRTrustAssessment;\n /**\n * What actually happened when the review was posted to GitHub (#4354).\n *\n * The review previously reported success whether or not the post landed: a\n * `createReview` rejection was logged and discarded, and a Rule-of-Two block\n * returned early, both leaving the CLI to print \"Review posted to GitHub.\"\n * over a review that does not exist. Callers must consult this rather than\n * inferring a successful post from a successful review.\n */\n readonly postOutcome: ReviewPostOutcome;\n}\n\n/**\n * A completed review before the posting step has run (#4354).\n *\n * Everything the reviewer aggregates is known before the post is attempted; the\n * outcome is stamped on afterwards. Keeping the two apart in the types is what\n * stops `postOutcome` from being defaulted to a hopeful value.\n */\nexport type PRReviewDraft = Omit<PRReviewResult, 'postOutcome'>;\n\n/** Terminal state of the GitHub review-posting step (#4354). */\nexport type ReviewPostOutcome =\n /** The review was created on GitHub. */\n | { readonly status: 'posted' }\n /** Posting was deliberately not attempted (dry-run, or a policy gate blocked it). */\n | { readonly status: 'skipped'; readonly reason: string }\n /** Posting was attempted and GitHub rejected it. */\n | { readonly status: 'failed'; readonly error: string };\n\n/**\n * Configuration for PR review.\n */\nexport interface PRReviewConfig {\n /** Experts to include in review */\n readonly experts: readonly ReviewCategory[];\n /** Maximum debate rounds */\n readonly maxDebateRounds: number;\n /** Consensus threshold (0-1) */\n readonly consensusThreshold: number;\n /** Minimum severity to report */\n readonly minSeverity: ReviewSeverity;\n /** Whether to post inline comments */\n readonly enableInlineComments: boolean;\n /** Whether to run in dry-run mode (no GitHub posting) */\n readonly dryRun: boolean;\n /** Whether to assess author reputation and gate on it (#3123). */\n readonly enableReputation: boolean;\n /** GitHub token for API access */\n readonly githubToken?: string | undefined;\n /** Model adapter configuration */\n readonly modelConfig?: {\n readonly temperature?: number;\n readonly maxTokens?: number;\n };\n}\n\n/**\n * Default PR review configuration.\n */\nexport const DEFAULT_PR_REVIEW_CONFIG: PRReviewConfig = {\n experts: ['security', 'code_quality', 'testing'],\n maxDebateRounds: 3,\n consensusThreshold: 0.7,\n minSeverity: 'low',\n enableInlineComments: true,\n dryRun: false,\n enableReputation: true,\n modelConfig: {\n temperature: 0.3,\n maxTokens: 8192,\n },\n};\n\n/**\n * Zod schema for PR review configuration.\n */\nexport const PRReviewConfigSchema = z.object({\n experts: z\n .array(\n z.enum([\n 'security',\n 'performance',\n 'code_quality',\n 'testing',\n 'documentation',\n 'architecture',\n ])\n )\n .default(['security', 'code_quality', 'testing']),\n maxDebateRounds: z.number().int().min(1).max(10).default(3),\n consensusThreshold: z.number().min(0).max(1).default(0.7),\n minSeverity: z.enum(FINDING_SEVERITY_LEVELS).default('low'),\n enableInlineComments: z.boolean().default(true),\n dryRun: z.boolean().default(false),\n enableReputation: z.boolean().default(true),\n githubToken: z.string().optional(),\n modelConfig: z\n .object({\n temperature: z.number().min(0).max(2).default(0.3),\n maxTokens: z.number().int().positive().default(8192),\n })\n .optional(),\n});\n\n/**\n * Severity order for comparison. INVERTED vs sarif-types' SEVERITY_ORDER by\n * design (higher = more severe here, for descending sort); only the KEY SET is\n * shared. Derived from the canonical {@link FINDING_SEVERITY_LEVELS} so the keys\n * can't drift (#3570): critical→5 … info→1.\n */\nexport const SEVERITY_ORDER: Record<ReviewSeverity, number> = Object.fromEntries(\n FINDING_SEVERITY_LEVELS.map((level, index) => [level, FINDING_SEVERITY_LEVELS.length - index])\n) as Record<ReviewSeverity, number>;\n\n/**\n * Category display names.\n */\nexport const CATEGORY_DISPLAY_NAMES: Record<ReviewCategory, string> = {\n security: 'Security',\n performance: 'Performance',\n code_quality: 'Code Quality',\n testing: 'Testing',\n documentation: 'Documentation',\n architecture: 'Architecture',\n};\n\n/**\n * Severity emoji for GitHub comments.\n */\nexport const SEVERITY_EMOJI: Record<ReviewSeverity, string> = {\n critical: ':rotating_light:',\n high: ':warning:',\n medium: ':yellow_circle:',\n low: ':large_blue_circle:',\n info: ':information_source:',\n};\n\n/**\n * Decision emoji for GitHub comments.\n */\nexport const DECISION_EMOJI: Record<ReviewDecision, string> = {\n approve: ':white_check_mark:',\n request_changes: ':x:',\n comment: ':speech_balloon:',\n};\n","/**\n * SARIF Types and Security Finding Schema (#1682)\n *\n * Types for parsing SARIF (Static Analysis Results Interchange Format)\n * output from security scanners (Semgrep, CodeQL, Bandit, ESLint).\n * Normalizes findings into a unified schema for MCP tool consumption.\n *\n * @module security/sarif-types\n * (Source: Issue #1681, #1682 — Proactive Defensive Security)\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Unified Security Finding Schema\n// ============================================================================\n\n/**\n * Canonical 5-value finding-severity vocabulary (CVSS-aligned), most→least\n * severe. THE single source of truth — every 5-value finding-severity zod enum\n * (severity-consensus, finding-triage, agents/output-schemas, expert-types\n * VulnerabilitySeverity) and both SEVERITY_ORDER maps derive from this (#3570).\n * Tuple order is authoritative: SEVERITY_ORDER below maps it to ascending ranks.\n */\nexport const FINDING_SEVERITY_LEVELS = ['critical', 'high', 'medium', 'low', 'info'] as const;\n\n/** Severity levels aligned with CVSS and common scanner output. */\nexport const FindingSeveritySchema = z.enum(FINDING_SEVERITY_LEVELS);\nexport type FindingSeverity = z.infer<typeof FindingSeveritySchema>;\n\n/** A normalized security finding from any SARIF-compatible scanner. */\nexport const SecurityFindingSchema = z.object({\n /** Unique finding ID (scanner-specific rule ID). */\n id: z.string().min(1),\n /** Scanner that produced this finding. */\n scanner: z.string().min(1),\n /** Rule identifier (e.g., 'javascript.lang.security.detect-eval'). */\n rule: z.string().min(1),\n /** Normalized severity. */\n severity: FindingSeveritySchema,\n /** Human-readable description of the finding. */\n message: z.string().min(1).max(2000),\n /** File path where the finding was detected. */\n file: z.string().min(1),\n /** Start line number (1-based). */\n startLine: z.number().int().min(1),\n /** End line number (1-based, optional). */\n endLine: z.number().int().min(1).optional(),\n /** CWE identifiers (e.g., ['CWE-79', 'CWE-89']). */\n cweIds: z.array(z.string()).default([]),\n /** Scanner confidence (0-1). */\n confidence: z.number().min(0).max(1).default(0.5),\n /** Code snippet around the finding (optional). */\n snippet: z.string().max(500).optional(),\n /** Help URL for remediation guidance. */\n helpUrl: z.string().optional(),\n});\n\nexport type SecurityFinding = z.infer<typeof SecurityFindingSchema>;\n\n/** Result of parsing a SARIF file. */\nexport interface SarifParseResult {\n /** Scanner name extracted from SARIF. */\n readonly scanner: string;\n /** Total findings parsed. */\n readonly totalFindings: number;\n /** Findings sorted by severity (critical first). */\n readonly findings: readonly SecurityFinding[];\n /** Parsing errors (non-fatal). */\n readonly errors: readonly string[];\n}\n\n// ============================================================================\n// SARIF Input Types (subset of the SARIF 2.1.0 spec we need)\n// ============================================================================\n\n/** SARIF result level → our severity mapping. */\nexport const SARIF_LEVEL_MAP: Readonly<Record<string, FindingSeverity>> = {\n error: 'high',\n warning: 'medium',\n note: 'low',\n none: 'info',\n};\n\n/**\n * Severity order for sorting (lower = more severe). Derived from the canonical\n * tuple so it can never drift from {@link FINDING_SEVERITY_LEVELS} (#3570).\n */\nexport const SEVERITY_ORDER: Readonly<Record<FindingSeverity, number>> = Object.fromEntries(\n FINDING_SEVERITY_LEVELS.map((level, index) => [level, index])\n) as Record<FindingSeverity, number>;\n"],"mappings":"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","names":["z","z","SEVERITY_ORDER"]}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
lookupInTreeCapability,
|
|
14
14
|
ok,
|
|
15
15
|
resolveRetryAfterMs
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
17
17
|
|
|
18
18
|
// src/config/model-parameter-support.ts
|
|
19
19
|
function parseClaudeMajorMinor(bareId) {
|
|
@@ -834,4 +834,4 @@ export {
|
|
|
834
834
|
DEFAULT_COLLECT_STREAM_MAX_CHUNKS,
|
|
835
835
|
collectStream
|
|
836
836
|
};
|
|
837
|
-
//# sourceMappingURL=chunk-
|
|
837
|
+
//# sourceMappingURL=chunk-CBORIR4Y.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
emitClawGuardViolation
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-X7MLVGJV.js";
|
|
4
4
|
import {
|
|
5
5
|
CACHE_TIMEOUTS,
|
|
6
6
|
MCP_TIMEOUTS,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
getTimeProvider,
|
|
17
17
|
ok,
|
|
18
18
|
resolveToolClassGuardMs
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
20
20
|
import {
|
|
21
21
|
getNexusDataDir
|
|
22
22
|
} from "./chunk-NBMWONHE.js";
|
|
@@ -2067,4 +2067,4 @@ export {
|
|
|
2067
2067
|
VOTING_THRESHOLDS,
|
|
2068
2068
|
ConsensusMetricsSchema
|
|
2069
2069
|
};
|
|
2070
|
-
//# sourceMappingURL=chunk-
|
|
2070
|
+
//# sourceMappingURL=chunk-D6ZTSN34.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getErrorMessage,
|
|
5
5
|
getTimeProvider,
|
|
6
6
|
ok
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
8
8
|
|
|
9
9
|
// src/context/session-memory.ts
|
|
10
10
|
import * as fs from "fs";
|
|
@@ -352,4 +352,4 @@ export {
|
|
|
352
352
|
SessionMemory,
|
|
353
353
|
createSessionMemory
|
|
354
354
|
};
|
|
355
|
-
//# sourceMappingURL=chunk-
|
|
355
|
+
//# sourceMappingURL=chunk-DGLAEH7Y.js.map
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-6T3EPABN.js";
|
|
6
6
|
import {
|
|
7
7
|
SessionMemory
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DGLAEH7Y.js";
|
|
9
9
|
import {
|
|
10
10
|
StatsOnlyAdapter,
|
|
11
11
|
ensureSharedMemoryRegistry
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./chunk-KSQSWEFH.js";
|
|
16
16
|
import {
|
|
17
17
|
generateId
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-MTGMOLRO.js";
|
|
19
19
|
import {
|
|
20
20
|
ErrorCode,
|
|
21
21
|
NexusError,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
getTimeProvider,
|
|
29
29
|
ok,
|
|
30
30
|
setSharedMobiMemDbPathResolver
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-2SVIHHNJ.js";
|
|
32
32
|
import {
|
|
33
33
|
nexusDataPath
|
|
34
34
|
} from "./chunk-NBMWONHE.js";
|
|
@@ -5029,7 +5029,7 @@ var ToolMemoryManager = class {
|
|
|
5029
5029
|
*/
|
|
5030
5030
|
async recordBelief(subject, predicate, object, confidence = "medium") {
|
|
5031
5031
|
try {
|
|
5032
|
-
await this.beliefs.retain({
|
|
5032
|
+
const result = await this.beliefs.retain({
|
|
5033
5033
|
subject,
|
|
5034
5034
|
predicate,
|
|
5035
5035
|
object,
|
|
@@ -5037,8 +5037,15 @@ var ToolMemoryManager = class {
|
|
|
5037
5037
|
sourceType: BeliefSourceType.OBSERVATION,
|
|
5038
5038
|
sourceRef: "mcp-tool-execution"
|
|
5039
5039
|
});
|
|
5040
|
+
if (!result.ok) {
|
|
5041
|
+
this.log.debug("Failed to record belief", { subject, error: result.error.message });
|
|
5042
|
+
return { persisted: false, reason: result.error.message };
|
|
5043
|
+
}
|
|
5044
|
+
return { persisted: true };
|
|
5040
5045
|
} catch (error) {
|
|
5041
|
-
|
|
5046
|
+
const reason = getErrorMessage(error);
|
|
5047
|
+
this.log.debug("Failed to record belief", { subject, error: reason });
|
|
5048
|
+
return { persisted: false, reason };
|
|
5042
5049
|
}
|
|
5043
5050
|
}
|
|
5044
5051
|
/**
|
|
@@ -5117,24 +5124,25 @@ var ToolMemoryManager = class {
|
|
|
5117
5124
|
isAdaptiveMemoryAvailable() {
|
|
5118
5125
|
return this.adaptive !== null;
|
|
5119
5126
|
}
|
|
5120
|
-
/** Store knowledge with auto-extracted attributes (AgenticMemory).
|
|
5127
|
+
/** Store knowledge with auto-extracted attributes (AgenticMemory). */
|
|
5121
5128
|
async recordKnowledge(key, value, metadata) {
|
|
5122
|
-
if (this.agentic === null) return;
|
|
5129
|
+
if (this.agentic === null) return { persisted: false, reason: "agentic backend unavailable" };
|
|
5123
5130
|
try {
|
|
5124
5131
|
const result = await this.agentic.storeWithAttributes(key, value, metadata);
|
|
5125
5132
|
if (!result.ok) {
|
|
5126
5133
|
this.log.debug("Failed to record knowledge", { key, error: result.error.message });
|
|
5134
|
+
return { persisted: false, reason: result.error.message };
|
|
5127
5135
|
}
|
|
5136
|
+
return { persisted: true };
|
|
5128
5137
|
} catch (error) {
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
});
|
|
5138
|
+
const reason = getErrorMessage(error);
|
|
5139
|
+
this.log.debug("Knowledge recording failed", { key, error: reason });
|
|
5140
|
+
return { persisted: false, reason };
|
|
5133
5141
|
}
|
|
5134
5142
|
}
|
|
5135
|
-
/** Store a value in AdaptiveMemory with importance scoring.
|
|
5143
|
+
/** Store a value in AdaptiveMemory with importance scoring. */
|
|
5136
5144
|
async storeAdaptive(key, value, importance) {
|
|
5137
|
-
if (this.adaptive === null) return;
|
|
5145
|
+
if (this.adaptive === null) return { persisted: false, reason: "adaptive backend unavailable" };
|
|
5138
5146
|
try {
|
|
5139
5147
|
const level = importance >= 0.8 ? "high" : importance >= 0.6 ? "medium" : "low";
|
|
5140
5148
|
const result = await this.adaptive.store(key, value, {
|
|
@@ -5143,17 +5151,19 @@ var ToolMemoryManager = class {
|
|
|
5143
5151
|
});
|
|
5144
5152
|
if (!result.ok) {
|
|
5145
5153
|
this.log.debug("Failed to store adaptive memory", { key, error: result.error.message });
|
|
5154
|
+
return { persisted: false, reason: result.error.message };
|
|
5146
5155
|
}
|
|
5156
|
+
return { persisted: true };
|
|
5147
5157
|
} catch (error) {
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
});
|
|
5158
|
+
const reason = getErrorMessage(error);
|
|
5159
|
+
this.log.debug("Adaptive memory store failed", { key, error: reason });
|
|
5160
|
+
return { persisted: false, reason };
|
|
5152
5161
|
}
|
|
5153
5162
|
}
|
|
5154
|
-
/** Store a value in TypedMemory (via HybridMemoryBackend).
|
|
5163
|
+
/** Store a value in TypedMemory (via HybridMemoryBackend). */
|
|
5155
5164
|
async storeTyped(key, value, importance) {
|
|
5156
|
-
if (this.typedBackend === null)
|
|
5165
|
+
if (this.typedBackend === null)
|
|
5166
|
+
return { persisted: false, reason: "typed backend unavailable" };
|
|
5157
5167
|
try {
|
|
5158
5168
|
const result = await this.typedBackend.store(`semantic ${key}`, value, {
|
|
5159
5169
|
importance,
|
|
@@ -5161,12 +5171,13 @@ var ToolMemoryManager = class {
|
|
|
5161
5171
|
});
|
|
5162
5172
|
if (!result.ok) {
|
|
5163
5173
|
this.log.debug("Failed to store typed memory", { key, error: result.error.message });
|
|
5174
|
+
return { persisted: false, reason: result.error.message };
|
|
5164
5175
|
}
|
|
5176
|
+
return { persisted: true };
|
|
5165
5177
|
} catch (error) {
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
});
|
|
5178
|
+
const reason = getErrorMessage(error);
|
|
5179
|
+
this.log.debug("Typed memory store failed", { key, error: reason });
|
|
5180
|
+
return { persisted: false, reason };
|
|
5170
5181
|
}
|
|
5171
5182
|
}
|
|
5172
5183
|
/** Query knowledge with attribute-based search (AgenticMemory). Best-effort. */
|
|
@@ -5550,4 +5561,4 @@ export {
|
|
|
5550
5561
|
reinitializeMemoryBackends,
|
|
5551
5562
|
ToolMemoryManager
|
|
5552
5563
|
};
|
|
5553
|
-
//# sourceMappingURL=chunk-
|
|
5564
|
+
//# sourceMappingURL=chunk-EU7S5CDW.js.map
|