nexus-agents 2.91.0 → 2.92.1
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/{chunk-W7YQOXCJ.js → chunk-74AO4RKT.js} +2 -2
- package/dist/{chunk-PLFKZUVT.js → chunk-G3CYK3WA.js} +7 -5
- package/dist/{chunk-PLFKZUVT.js.map → chunk-G3CYK3WA.js.map} +1 -1
- package/dist/{chunk-3RZWLQSC.js → chunk-G5XKEUAP.js} +74 -2
- package/dist/chunk-G5XKEUAP.js.map +1 -0
- package/dist/{chunk-6IV43POQ.js → chunk-L6JZCAFH.js} +96 -624
- package/dist/chunk-L6JZCAFH.js.map +1 -0
- package/dist/chunk-NR4NSTJH.js +547 -0
- package/dist/chunk-NR4NSTJH.js.map +1 -0
- package/dist/{chunk-X2M7OF27.js → chunk-OK6U5N5Y.js} +3 -1
- package/dist/chunk-OK6U5N5Y.js.map +1 -0
- package/dist/{chunk-DH4V6S5K.js → chunk-ZNR3ZVC6.js} +3 -3
- package/dist/cli.js +43 -20
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +190 -190
- package/dist/index.js +19 -17
- package/dist/index.js.map +1 -1
- package/dist/{issue-triage-CDSHKFPP.js → issue-triage-FVZOVIRX.js} +3 -2
- package/dist/{pr-reviewer-helpers-WYPUYQ2U.js → pr-reviewer-helpers-RBUEJI6V.js} +14 -3
- package/dist/{setup-command-B5QPHCKY.js → setup-command-AZAWBZOP.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-3RZWLQSC.js.map +0 -1
- package/dist/chunk-6IV43POQ.js.map +0 -1
- package/dist/chunk-X2M7OF27.js.map +0 -1
- /package/dist/{chunk-W7YQOXCJ.js.map → chunk-74AO4RKT.js.map} +0 -0
- /package/dist/{chunk-DH4V6S5K.js.map → chunk-ZNR3ZVC6.js.map} +0 -0
- /package/dist/{issue-triage-CDSHKFPP.js.map → issue-triage-FVZOVIRX.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-WYPUYQ2U.js.map → pr-reviewer-helpers-RBUEJI6V.js.map} +0 -0
- /package/dist/{setup-command-B5QPHCKY.js.map → setup-command-AZAWBZOP.js.map} +0 -0
|
@@ -7,6 +7,7 @@ var DEFAULT_PR_REVIEW_CONFIG = {
|
|
|
7
7
|
minSeverity: "low",
|
|
8
8
|
enableInlineComments: true,
|
|
9
9
|
dryRun: false,
|
|
10
|
+
enableReputation: true,
|
|
10
11
|
modelConfig: {
|
|
11
12
|
temperature: 0.3,
|
|
12
13
|
maxTokens: 8192
|
|
@@ -28,6 +29,7 @@ var PRReviewConfigSchema = z.object({
|
|
|
28
29
|
minSeverity: z.enum(["critical", "high", "medium", "low", "info"]).default("low"),
|
|
29
30
|
enableInlineComments: z.boolean().default(true),
|
|
30
31
|
dryRun: z.boolean().default(false),
|
|
32
|
+
enableReputation: z.boolean().default(true),
|
|
31
33
|
githubToken: z.string().optional(),
|
|
32
34
|
modelConfig: z.object({
|
|
33
35
|
temperature: z.number().min(0).max(2).default(0.3),
|
|
@@ -69,4 +71,4 @@ export {
|
|
|
69
71
|
SEVERITY_EMOJI,
|
|
70
72
|
DECISION_EMOJI
|
|
71
73
|
};
|
|
72
|
-
//# sourceMappingURL=chunk-
|
|
74
|
+
//# sourceMappingURL=chunk-OK6U5N5Y.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dogfooding/pr-review-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';\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 = 'critical' | 'high' | 'medium' | 'low' | 'info';\n\n/**\n * Review category for organizing findings.\n */\nexport type ReviewCategory =\n | 'security'\n | 'performance'\n | 'code_quality'\n | 'testing'\n | 'documentation'\n | '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 /** 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\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(['critical', 'high', 'medium', 'low', 'info']).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.\n */\nexport const SEVERITY_ORDER: Record<ReviewSeverity, number> = {\n critical: 5,\n high: 4,\n medium: 3,\n low: 2,\n info: 1,\n};\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"],"mappings":";AAUA,SAAS,SAAS;AA+NX,IAAM,2BAA2C;AAAA,EACtD,SAAS,CAAC,YAAY,gBAAgB,SAAS;AAAA,EAC/C,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,aAAa;AAAA,IACX,aAAa;AAAA,IACb,WAAW;AAAA,EACb;AACF;AAKO,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,SAAS,EACN;AAAA,IACC,EAAE,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH,EACC,QAAQ,CAAC,YAAY,gBAAgB,SAAS,CAAC;AAAA,EAClD,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC;AAAA,EAC1D,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG;AAAA,EACxD,aAAa,EAAE,KAAK,CAAC,YAAY,QAAQ,UAAU,OAAO,MAAM,CAAC,EAAE,QAAQ,KAAK;AAAA,EAChF,sBAAsB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EAC9C,QAAQ,EAAE,QAAQ,EAAE,QAAQ,KAAK;AAAA,EACjC,kBAAkB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,EAC1C,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,aAAa,EACV,OAAO;AAAA,IACN,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG;AAAA,IACjD,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EACrD,CAAC,EACA,SAAS;AACd,CAAC;AAKM,IAAM,iBAAiD;AAAA,EAC5D,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AACR;AAKO,IAAM,yBAAyD;AAAA,EACpE,UAAU;AAAA,EACV,aAAa;AAAA,EACb,cAAc;AAAA,EACd,SAAS;AAAA,EACT,eAAe;AAAA,EACf,cAAc;AAChB;AAKO,IAAM,iBAAiD;AAAA,EAC5D,UAAU;AAAA,EACV,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,MAAM;AACR;AAKO,IAAM,iBAAiD;AAAA,EAC5D,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,SAAS;AACX;","names":[]}
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
} from "./chunk-CH7QIDHQ.js";
|
|
41
41
|
|
|
42
42
|
// src/version.ts
|
|
43
|
-
var VERSION = true ? "2.
|
|
43
|
+
var VERSION = true ? "2.92.1" : "dev";
|
|
44
44
|
|
|
45
45
|
// src/config/schemas-core.ts
|
|
46
46
|
import { z } from "zod";
|
|
@@ -2096,7 +2096,7 @@ async function runDoctorFix(result) {
|
|
|
2096
2096
|
writeLine2("\u2500".repeat(40));
|
|
2097
2097
|
let fixCount = 0;
|
|
2098
2098
|
if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
|
|
2099
|
-
const { runSetup } = await import("./setup-command-
|
|
2099
|
+
const { runSetup } = await import("./setup-command-AZAWBZOP.js");
|
|
2100
2100
|
const setupResult = runSetup({
|
|
2101
2101
|
skipMcp: true,
|
|
2102
2102
|
skipRules: true,
|
|
@@ -2208,4 +2208,4 @@ export {
|
|
|
2208
2208
|
startStdioServer,
|
|
2209
2209
|
closeServer
|
|
2210
2210
|
};
|
|
2211
|
-
//# sourceMappingURL=chunk-
|
|
2211
|
+
//# sourceMappingURL=chunk-ZNR3ZVC6.js.map
|
package/dist/cli.js
CHANGED
|
@@ -7,11 +7,13 @@ import {
|
|
|
7
7
|
determineApproval,
|
|
8
8
|
determineDecision,
|
|
9
9
|
extractSummary,
|
|
10
|
+
fetchAccountAgeDays,
|
|
10
11
|
formatReviewComment,
|
|
12
|
+
gatePRAuthor,
|
|
11
13
|
generateSummary,
|
|
12
14
|
parseFindings,
|
|
13
15
|
sumFindings
|
|
14
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-G5XKEUAP.js";
|
|
15
17
|
import "./chunk-AQTHLUCP.js";
|
|
16
18
|
import {
|
|
17
19
|
buildOpenAICompatAdapters,
|
|
@@ -22,7 +24,7 @@ import {
|
|
|
22
24
|
import {
|
|
23
25
|
setupCommandAsync,
|
|
24
26
|
verifyCommand
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-74AO4RKT.js";
|
|
26
28
|
import "./chunk-2SMTCNXP.js";
|
|
27
29
|
import {
|
|
28
30
|
AuthHandler,
|
|
@@ -162,14 +164,14 @@ import {
|
|
|
162
164
|
validateCommand,
|
|
163
165
|
validateWorkflow,
|
|
164
166
|
wrapInMarkdownFence
|
|
165
|
-
} from "./chunk-
|
|
167
|
+
} from "./chunk-G3CYK3WA.js";
|
|
166
168
|
import {
|
|
167
169
|
resolveToken
|
|
168
170
|
} from "./chunk-EAT4GTMT.js";
|
|
169
171
|
import {
|
|
170
172
|
CATEGORY_DISPLAY_NAMES,
|
|
171
173
|
DEFAULT_PR_REVIEW_CONFIG
|
|
172
|
-
} from "./chunk-
|
|
174
|
+
} from "./chunk-OK6U5N5Y.js";
|
|
173
175
|
import "./chunk-E6W4Z6GN.js";
|
|
174
176
|
import "./chunk-3LKW4IEW.js";
|
|
175
177
|
import {
|
|
@@ -205,10 +207,13 @@ import {
|
|
|
205
207
|
classifyTrust,
|
|
206
208
|
createFullGitHubProvider,
|
|
207
209
|
evaluatePolicy,
|
|
208
|
-
parsePRUrl
|
|
209
|
-
|
|
210
|
-
} from "./chunk-6IV43POQ.js";
|
|
210
|
+
parsePRUrl
|
|
211
|
+
} from "./chunk-L6JZCAFH.js";
|
|
211
212
|
import "./chunk-EFHZHCF2.js";
|
|
213
|
+
import {
|
|
214
|
+
ReputationCache,
|
|
215
|
+
sanitizeInput
|
|
216
|
+
} from "./chunk-NR4NSTJH.js";
|
|
212
217
|
import "./chunk-57HMLBYN.js";
|
|
213
218
|
import "./chunk-HFOQKCD2.js";
|
|
214
219
|
import "./chunk-3ACDP4E6.js";
|
|
@@ -235,7 +240,7 @@ import {
|
|
|
235
240
|
loadConfig,
|
|
236
241
|
runDoctor,
|
|
237
242
|
validateNexusEnv
|
|
238
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-ZNR3ZVC6.js";
|
|
239
244
|
import "./chunk-SFZESA5O.js";
|
|
240
245
|
import "./chunk-6Q33PBXC.js";
|
|
241
246
|
import {
|
|
@@ -2840,10 +2845,12 @@ var PRReviewer = class {
|
|
|
2840
2845
|
config;
|
|
2841
2846
|
observer;
|
|
2842
2847
|
adapter;
|
|
2848
|
+
reputationCache;
|
|
2843
2849
|
constructor(config, adapter) {
|
|
2844
2850
|
this.config = { ...DEFAULT_PR_REVIEW_CONFIG, ...config };
|
|
2845
2851
|
this.observer = new SwarmObserver();
|
|
2846
2852
|
this.adapter = adapter ?? void 0;
|
|
2853
|
+
this.reputationCache = new ReputationCache();
|
|
2847
2854
|
}
|
|
2848
2855
|
/**
|
|
2849
2856
|
* Reviews a pull request using multi-agent collaboration.
|
|
@@ -2857,7 +2864,7 @@ var PRReviewer = class {
|
|
|
2857
2864
|
const { owner, repo, prNumber } = parseResult.value;
|
|
2858
2865
|
const fetchResult = await this.fetchPRData(owner, repo, prNumber);
|
|
2859
2866
|
if (!fetchResult.ok) return fetchResult;
|
|
2860
|
-
const { metadata: prMetadata, provider } = fetchResult.value;
|
|
2867
|
+
const { metadata: prMetadata, provider, accountAgeDays } = fetchResult.value;
|
|
2861
2868
|
const trustResult = this.classifyPRAuthor(prMetadata);
|
|
2862
2869
|
logger2.info("PR author trust classified", {
|
|
2863
2870
|
prNumber,
|
|
@@ -2866,10 +2873,17 @@ var PRReviewer = class {
|
|
|
2866
2873
|
userRole: trustResult.userRole,
|
|
2867
2874
|
isAllowlisted: trustResult.isAllowlisted
|
|
2868
2875
|
});
|
|
2876
|
+
const { gateDecision, trustAssessment } = gatePRAuthor(
|
|
2877
|
+
prMetadata,
|
|
2878
|
+
trustResult,
|
|
2879
|
+
accountAgeDays,
|
|
2880
|
+
this.reputationCache,
|
|
2881
|
+
this.config.enableReputation
|
|
2882
|
+
);
|
|
2869
2883
|
const expertReviews = await this.runExpertReviews(prMetadata, traceId);
|
|
2870
|
-
const result = this.aggregateReviews(prMetadata, expertReviews, startTime);
|
|
2884
|
+
const result = this.aggregateReviews(prMetadata, expertReviews, startTime, trustAssessment);
|
|
2871
2885
|
if (!this.config.dryRun) {
|
|
2872
|
-
await this.postReviewToGitHub(provider, parseResult.value, result,
|
|
2886
|
+
await this.postReviewToGitHub(provider, parseResult.value, result, gateDecision);
|
|
2873
2887
|
}
|
|
2874
2888
|
logger2.info("PR review completed", {
|
|
2875
2889
|
prNumber,
|
|
@@ -3053,7 +3067,7 @@ ${file.patch}
|
|
|
3053
3067
|
/**
|
|
3054
3068
|
* Aggregates individual expert reviews into final result.
|
|
3055
3069
|
*/
|
|
3056
|
-
aggregateReviews(pr, reviews, startTime) {
|
|
3070
|
+
aggregateReviews(pr, reviews, startTime, trustAssessment) {
|
|
3057
3071
|
const allFindings = reviews.flatMap((r) => r.findings);
|
|
3058
3072
|
const decision = determineDecision(reviews, allFindings);
|
|
3059
3073
|
const consensusScore = calculateConsensus(reviews);
|
|
@@ -3069,7 +3083,8 @@ ${file.patch}
|
|
|
3069
3083
|
expertCount: reviews.length,
|
|
3070
3084
|
consensusScore,
|
|
3071
3085
|
debateRounds: 1,
|
|
3072
|
-
timestamp: getTimeProvider().nowIso()
|
|
3086
|
+
timestamp: getTimeProvider().nowIso(),
|
|
3087
|
+
trustAssessment
|
|
3073
3088
|
};
|
|
3074
3089
|
}
|
|
3075
3090
|
/**
|
|
@@ -3079,8 +3094,8 @@ ${file.patch}
|
|
|
3079
3094
|
* from the untrusted PR author.
|
|
3080
3095
|
* (Source: Issue #828 — Wire policy gate into production pipeline)
|
|
3081
3096
|
*/
|
|
3082
|
-
async postReviewToGitHub(provider, pr, result,
|
|
3083
|
-
const policyResult = this.auditReviewAction(
|
|
3097
|
+
async postReviewToGitHub(provider, pr, result, gateDecision) {
|
|
3098
|
+
const policyResult = this.auditReviewAction(gateDecision.enforcedTier);
|
|
3084
3099
|
if (policyResult.hasRuleOfTwoViolation) {
|
|
3085
3100
|
logger2.warn("Rule of Two: review posting blocked", {
|
|
3086
3101
|
prNumber: pr.prNumber,
|
|
@@ -3094,17 +3109,20 @@ ${file.patch}
|
|
|
3094
3109
|
violations: policyResult.violations
|
|
3095
3110
|
});
|
|
3096
3111
|
}
|
|
3097
|
-
const { formatReviewComment: formatReviewComment2 } = await import("./pr-reviewer-helpers-
|
|
3112
|
+
const { formatReviewComment: formatReviewComment2 } = await import("./pr-reviewer-helpers-RBUEJI6V.js");
|
|
3098
3113
|
const body = formatReviewComment2(result);
|
|
3099
3114
|
const postResult = await provider.createReview(pr.prNumber, body, result.decision);
|
|
3100
3115
|
if (!postResult.ok) {
|
|
3101
3116
|
logger2.error("Failed to post review", postResult.error);
|
|
3102
3117
|
}
|
|
3103
3118
|
}
|
|
3104
|
-
/**
|
|
3105
|
-
|
|
3119
|
+
/**
|
|
3120
|
+
* Audits review posting against the policy gate. Gates on the reputation-
|
|
3121
|
+
* reconciled `enforcedTier` (#3123) rather than the raw classifier tier.
|
|
3122
|
+
*/
|
|
3123
|
+
auditReviewAction(enforcedTier) {
|
|
3106
3124
|
const context = {
|
|
3107
|
-
inputTrustTier:
|
|
3125
|
+
inputTrustTier: enforcedTier,
|
|
3108
3126
|
hasWriteAccess: true,
|
|
3109
3127
|
hasSecretAccess: true
|
|
3110
3128
|
};
|
|
@@ -3135,6 +3153,7 @@ ${file.patch}
|
|
|
3135
3153
|
const detailResult = await provider.getPullRequestDetail(prNumber);
|
|
3136
3154
|
if (!detailResult.ok) return err(detailResult.error);
|
|
3137
3155
|
const detail = detailResult.value;
|
|
3156
|
+
const accountAgeDays = this.config.enableReputation ? await fetchAccountAgeDays(provider, detail.author) : void 0;
|
|
3138
3157
|
const metadata = {
|
|
3139
3158
|
number: detail.number,
|
|
3140
3159
|
title: detail.title,
|
|
@@ -3160,7 +3179,11 @@ ${file.patch}
|
|
|
3160
3179
|
additions: detail.additions,
|
|
3161
3180
|
deletions: detail.deletions
|
|
3162
3181
|
};
|
|
3163
|
-
return ok({
|
|
3182
|
+
return ok({
|
|
3183
|
+
metadata,
|
|
3184
|
+
provider,
|
|
3185
|
+
...accountAgeDays !== void 0 ? { accountAgeDays } : {}
|
|
3186
|
+
});
|
|
3164
3187
|
}
|
|
3165
3188
|
/**
|
|
3166
3189
|
* Gets the SwarmObserver for debugging.
|