nexus-agents 2.92.0 → 2.92.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/{chunk-LOBVTRQQ.js → chunk-3HVSXLPL.js} +3 -3
  2. package/dist/{chunk-HPV2D4HN.js → chunk-F47QKVPH.js} +4 -4
  3. package/dist/{chunk-RS6RGSYG.js → chunk-G5XKEUAP.js} +46 -3
  4. package/dist/chunk-G5XKEUAP.js.map +1 -0
  5. package/dist/{chunk-S4UF577T.js → chunk-OK6U5N5Y.js} +1 -1
  6. package/dist/chunk-OK6U5N5Y.js.map +1 -0
  7. package/dist/{chunk-4N54BTZU.js → chunk-UYOHV3EG.js} +30 -8
  8. package/dist/chunk-UYOHV3EG.js.map +1 -0
  9. package/dist/{chunk-VW2LBC7B.js → chunk-XNBPE6WG.js} +2 -2
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.js +23 -40
  12. package/dist/cli.js.map +1 -1
  13. package/dist/{consensus-vote-B6W7YQ6K.js → consensus-vote-VSRNSZ5J.js} +4 -2
  14. package/dist/{consensus-vote-types-COAhHVIp.d.ts → consensus-vote-types-WGBFeT7y.d.ts} +6 -0
  15. package/dist/index.d.ts +192 -192
  16. package/dist/index.js +5 -5
  17. package/dist/{pr-reviewer-helpers-7D2W5HTO.js → pr-reviewer-helpers-RBUEJI6V.js} +7 -3
  18. package/dist/{setup-command-UN3XDJ2H.js → setup-command-BMELLUUX.js} +3 -3
  19. package/package.json +1 -1
  20. package/dist/chunk-4N54BTZU.js.map +0 -1
  21. package/dist/chunk-RS6RGSYG.js.map +0 -1
  22. package/dist/chunk-S4UF577T.js.map +0 -1
  23. /package/dist/{chunk-LOBVTRQQ.js.map → chunk-3HVSXLPL.js.map} +0 -0
  24. /package/dist/{chunk-HPV2D4HN.js.map → chunk-F47QKVPH.js.map} +0 -0
  25. /package/dist/{chunk-VW2LBC7B.js.map → chunk-XNBPE6WG.js.map} +0 -0
  26. /package/dist/{consensus-vote-B6W7YQ6K.js.map → consensus-vote-VSRNSZ5J.js.map} +0 -0
  27. /package/dist/{pr-reviewer-helpers-7D2W5HTO.js.map → pr-reviewer-helpers-RBUEJI6V.js.map} +0 -0
  28. /package/dist/{setup-command-UN3XDJ2H.js.map → setup-command-BMELLUUX.js.map} +0 -0
@@ -40,7 +40,7 @@ import {
40
40
  } from "./chunk-CH7QIDHQ.js";
41
41
 
42
42
  // src/version.ts
43
- var VERSION = true ? "2.92.0" : "dev";
43
+ var VERSION = true ? "2.92.2" : "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-UN3XDJ2H.js");
2099
+ const { runSetup } = await import("./setup-command-BMELLUUX.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-LOBVTRQQ.js.map
2211
+ //# sourceMappingURL=chunk-3HVSXLPL.js.map
@@ -42,7 +42,7 @@ import {
42
42
  writeJobComplete,
43
43
  writeJobFailed,
44
44
  writeJobPending
45
- } from "./chunk-4N54BTZU.js";
45
+ } from "./chunk-UYOHV3EG.js";
46
46
  import {
47
47
  REGISTRY_PATH,
48
48
  getProjectRoot,
@@ -84,7 +84,7 @@ import {
84
84
  DEFAULT_TASK_TTL_MS,
85
85
  DEFAULT_TOOL_RATE_LIMITS,
86
86
  clampTaskTtl
87
- } from "./chunk-LOBVTRQQ.js";
87
+ } from "./chunk-3HVSXLPL.js";
88
88
  import {
89
89
  getAvailabilityCache,
90
90
  resolveFallback
@@ -43548,7 +43548,7 @@ ${contextBlock}`;
43548
43548
  const strategy = config.votingStrategy ?? "higher_order";
43549
43549
  await postProgress(config, "Vote", `Running consensus with ${strategy} strategy...`);
43550
43550
  try {
43551
- const { executeVoting } = await import("./consensus-vote-B6W7YQ6K.js");
43551
+ const { executeVoting } = await import("./consensus-vote-VSRNSZ5J.js");
43552
43552
  const votingResult = await executeVoting(
43553
43553
  {
43554
43554
  proposal: plan.slice(0, 4e3),
@@ -51876,4 +51876,4 @@ export {
51876
51876
  detectBackend,
51877
51877
  createTaskTracker
51878
51878
  };
51879
- //# sourceMappingURL=chunk-HPV2D4HN.js.map
51879
+ //# sourceMappingURL=chunk-F47QKVPH.js.map
@@ -3,19 +3,38 @@ import {
3
3
  DECISION_EMOJI,
4
4
  SEVERITY_EMOJI,
5
5
  SEVERITY_ORDER
6
- } from "./chunk-S4UF577T.js";
6
+ } from "./chunk-OK6U5N5Y.js";
7
7
  import {
8
8
  assessReputation,
9
+ gateWithReputation,
10
+ resolveReputationGatingMode,
9
11
  sanitizeInput
10
12
  } from "./chunk-NR4NSTJH.js";
13
+ import {
14
+ createLogger,
15
+ getTimeProvider
16
+ } from "./chunk-W5I6L4UT.js";
11
17
 
12
18
  // src/dogfooding/pr-reviewer-helpers.ts
13
19
  import { randomUUID } from "crypto";
14
- function assessPRReputation(pr, cache, enableReputation) {
20
+ var repLogger = createLogger({ component: "PRReviewer.reputation" });
21
+ async function fetchAccountAgeDays(provider, username) {
22
+ try {
23
+ const result = await provider.fetchUserMetadata(username);
24
+ if (!result.ok) return void 0;
25
+ const createdMs = Date.parse(result.value.createdAt);
26
+ if (!Number.isFinite(createdMs)) return void 0;
27
+ return Math.floor((getTimeProvider().now() - createdMs) / 864e5);
28
+ } catch {
29
+ return void 0;
30
+ }
31
+ }
32
+ function assessPRReputation(pr, cache, enableReputation, accountAgeDays) {
15
33
  if (!enableReputation) return void 0;
16
34
  const sanitizeResult = sanitizeInput(pr.body, "unknown", pr.author);
17
35
  const metadata = {
18
36
  username: pr.author,
37
+ ...accountAgeDays !== void 0 ? { accountAgeDays } : {},
19
38
  authorAssociation: pr.authorAssociation,
20
39
  injectionFlags: sanitizeResult.injectionFlags
21
40
  };
@@ -28,12 +47,34 @@ function buildPRTrustAssessment(trustResult, reputation, gateDecision) {
28
47
  userRole: trustResult.userRole,
29
48
  isAllowlisted: trustResult.isAllowlisted,
30
49
  reputationScore: reputation?.reputationScore,
50
+ suspiciousSignals: isTier1 ? [] : reputation?.suspiciousSignals ?? [],
31
51
  isSuspicious: isTier1 ? false : reputation?.isSuspicious ?? false,
32
52
  enforcedTrustTier: gateDecision.enforcedTier,
33
53
  reputationReconciledTier: gateDecision.reconciledTier,
34
54
  gatingMode: gateDecision.mode
35
55
  };
36
56
  }
57
+ function gatePRAuthor(pr, trustResult, accountAgeDays, cache, enableReputation) {
58
+ const reputation = assessPRReputation(pr, cache, enableReputation, accountAgeDays);
59
+ const gateDecision = gateWithReputation(
60
+ trustResult.trustTier,
61
+ reputation,
62
+ resolveReputationGatingMode()
63
+ );
64
+ if (gateDecision.demotionSuppressed) {
65
+ repLogger.warn("Reputation demotion suppressed by gating mode (would block under enforce)", {
66
+ prNumber: pr.number,
67
+ author: pr.author,
68
+ mode: gateDecision.mode,
69
+ classifierTier: trustResult.trustTier,
70
+ reconciledTier: gateDecision.reconciledTier
71
+ });
72
+ }
73
+ return {
74
+ gateDecision,
75
+ trustAssessment: buildPRTrustAssessment(trustResult, reputation, gateDecision)
76
+ };
77
+ }
37
78
  function parseSeverity(value) {
38
79
  if (typeof value === "string") {
39
80
  const lower = value.toLowerCase();
@@ -228,8 +269,10 @@ function createFailedReview(expertId, category, durationMs, error) {
228
269
  }
229
270
 
230
271
  export {
272
+ fetchAccountAgeDays,
231
273
  assessPRReputation,
232
274
  buildPRTrustAssessment,
275
+ gatePRAuthor,
233
276
  parseSeverity,
234
277
  parseCategory,
235
278
  extractSummary,
@@ -245,4 +288,4 @@ export {
245
288
  formatReviewComment,
246
289
  createFailedReview
247
290
  };
248
- //# sourceMappingURL=chunk-RS6RGSYG.js.map
291
+ //# sourceMappingURL=chunk-G5XKEUAP.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 PRReviewResult,\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 {\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 const hasCritical = findings.some((f) => f.severity === 'critical');\n const hasHigh = findings.some((f) => f.severity === 'high');\n const allApproved = reviews.every((r) => r.approved);\n\n if (hasCritical) return 'request_changes';\n if (hasHigh && !allApproved) return 'request_changes';\n if (findings.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: PRReviewResult): 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: PRReviewResult): 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: PRReviewResult): 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 approved: true, // Don't block on failures\n summary: `Review failed: ${error}`,\n findings: [],\n durationMs,\n confidence: 0,\n };\n}\n"],"mappings":"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","names":[]}
@@ -71,4 +71,4 @@ export {
71
71
  SEVERITY_EMOJI,
72
72
  DECISION_EMOJI
73
73
  };
74
- //# sourceMappingURL=chunk-S4UF577T.js.map
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":[]}
@@ -7990,6 +7990,9 @@ function buildResponse(input, result) {
7990
7990
  if (input.threshold !== void 0) {
7991
7991
  response.threshold = input.threshold;
7992
7992
  }
7993
+ if (result.policyReason !== void 0) {
7994
+ response.policyReason = result.policyReason;
7995
+ }
7993
7996
  if (result.strategy === "higher_order" && result.higherOrderResult) {
7994
7997
  response.higherOrderMetadata = {
7995
7998
  posteriorApproval: result.higherOrderResult.posteriorApproval,
@@ -8971,15 +8974,27 @@ function createEmptyConsensusResult(proposal, algorithm) {
8971
8974
  durationMs: 0
8972
8975
  };
8973
8976
  }
8974
- function createPolicyFailedResult(proposal, algorithm, reason) {
8977
+ function createPolicyFailedResult(proposal, algorithm, reason, votes) {
8975
8978
  const now = (/* @__PURE__ */ new Date()).toISOString();
8979
+ const voteMap = /* @__PURE__ */ new Map();
8980
+ let approve = 0;
8981
+ let reject = 0;
8982
+ let abstain = 0;
8983
+ for (const v of votes) {
8984
+ if (v.source === "error") continue;
8985
+ voteMap.set(v.role, v.vote);
8986
+ if (v.vote.decision === "approve") approve++;
8987
+ else if (v.vote.decision === "reject") reject++;
8988
+ else abstain++;
8989
+ }
8990
+ const responding = approve + reject + abstain;
8976
8991
  return {
8977
8992
  proposalId: "error-policy-short-circuit",
8978
8993
  proposal: { title: `MCP Consensus Vote \u2014 ${reason}`, description: proposal, algorithm },
8979
8994
  outcome: "rejected",
8980
- votes: /* @__PURE__ */ new Map(),
8981
- voteCounts: { approve: 0, reject: 0, abstain: 0, total: 0 },
8982
- approvalPercentage: 0,
8995
+ votes: voteMap,
8996
+ voteCounts: { approve, reject, abstain, total: responding },
8997
+ approvalPercentage: responding > 0 ? approve / responding * 100 : 0,
8983
8998
  quorumReached: false,
8984
8999
  startedAt: now,
8985
9000
  closedAt: now,
@@ -9134,11 +9149,14 @@ function buildPolicyShortCircuitResult(args) {
9134
9149
  return {
9135
9150
  proposal: args.input.proposal,
9136
9151
  threshold: args.algorithm,
9137
- result: createPolicyFailedResult(args.input.proposal, args.algorithm, args.reason),
9152
+ result: createPolicyFailedResult(args.input.proposal, args.algorithm, args.reason, args.votes),
9138
9153
  votes: args.votes,
9139
9154
  totalTimeMs,
9140
9155
  simulateVotes: args.input.simulateVotes,
9141
- strategy: args.strategy
9156
+ strategy: args.strategy,
9157
+ // #3124: surface WHY a high-approval result is still 'rejected' so callers
9158
+ // don't mistake a fail-closed policy short-circuit for a genuine rejection.
9159
+ policyReason: args.reason
9142
9160
  };
9143
9161
  }
9144
9162
  async function maybeEscalateContrarian(input, outcome, logger11, opts) {
@@ -9433,7 +9451,10 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
9433
9451
  improvementOverBaseline: z12.number(),
9434
9452
  downweightedAgents: z12.array(z12.string().max(100)).max(10),
9435
9453
  reasoning: z12.string().max(2e3)
9436
- }).optional()
9454
+ }).optional(),
9455
+ // #3124: explains a `rejected` decision that coexists with a high
9456
+ // approvalPercentage (an error-policy short-circuit, e.g. fail_closed).
9457
+ policyReason: z12.string().max(200).optional()
9437
9458
  };
9438
9459
  function registerConsensusVoteTool(server, deps) {
9439
9460
  const logger11 = deps.logger ?? createLogger({ tool: "consensus_vote" });
@@ -9599,8 +9620,9 @@ export {
9599
9620
  ConsensusVoteInputSchema,
9600
9621
  warnIfSimulatedOutsideTests,
9601
9622
  resetCorrelationTracker,
9623
+ createPolicyFailedResult,
9602
9624
  executeVoting,
9603
9625
  CONSENSUS_VOTE_OUTPUT_SCHEMA,
9604
9626
  registerConsensusVoteTool
9605
9627
  };
9606
- //# sourceMappingURL=chunk-4N54BTZU.js.map
9628
+ //# sourceMappingURL=chunk-UYOHV3EG.js.map