@nxuss/lemma 0.9.1 → 0.9.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/README.md +74 -10
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +52 -1
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/mcp/tools.d.ts.map +1 -1
- package/dist/cjs/mcp/tools.js +878 -0
- package/dist/cjs/mcp/tools.js.map +1 -1
- package/dist/cjs/pr-review/PRReviewEngine.d.ts +4 -0
- package/dist/cjs/pr-review/PRReviewEngine.d.ts.map +1 -0
- package/dist/cjs/pr-review/PRReviewEngine.js +203 -0
- package/dist/cjs/pr-review/PRReviewEngine.js.map +1 -0
- package/dist/cjs/pr-review/ReviewStore.d.ts +9 -0
- package/dist/cjs/pr-review/ReviewStore.d.ts.map +1 -0
- package/dist/cjs/pr-review/ReviewStore.js +29 -0
- package/dist/cjs/pr-review/ReviewStore.js.map +1 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.d.ts +18 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.js +156 -0
- package/dist/cjs/pr-review/adapters/AzureDevOpsAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.d.ts +18 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.js +106 -0
- package/dist/cjs/pr-review/adapters/GitHubAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.d.ts +19 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.js +137 -0
- package/dist/cjs/pr-review/adapters/GitLabAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.d.ts +14 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.js +3 -0
- package/dist/cjs/pr-review/adapters/GitPlatformAdapter.js.map +1 -0
- package/dist/cjs/pr-review/adapters/index.d.ts +5 -0
- package/dist/cjs/pr-review/adapters/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/adapters/index.js +10 -0
- package/dist/cjs/pr-review/adapters/index.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.js +154 -0
- package/dist/cjs/pr-review/analyzers/QualityGrader.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.js +151 -0
- package/dist/cjs/pr-review/analyzers/RegressionDetector.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.js +110 -0
- package/dist/cjs/pr-review/analyzers/SecurityScanner.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.d.ts +7 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.js +237 -0
- package/dist/cjs/pr-review/analyzers/StaticAnalyzer.js.map +1 -0
- package/dist/cjs/pr-review/analyzers/index.d.ts +9 -0
- package/dist/cjs/pr-review/analyzers/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/analyzers/index.js +12 -0
- package/dist/cjs/pr-review/analyzers/index.js.map +1 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.d.ts +23 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.d.ts.map +1 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.js +100 -0
- package/dist/cjs/pr-review/bridge/BrainBridge.js.map +1 -0
- package/dist/cjs/pr-review/bridge/index.d.ts +2 -0
- package/dist/cjs/pr-review/bridge/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/bridge/index.js +6 -0
- package/dist/cjs/pr-review/bridge/index.js.map +1 -0
- package/dist/cjs/pr-review/index.d.ts +5 -0
- package/dist/cjs/pr-review/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/index.js +12 -0
- package/dist/cjs/pr-review/index.js.map +1 -0
- package/dist/cjs/pr-review/reviewRunner.d.ts +25 -0
- package/dist/cjs/pr-review/reviewRunner.d.ts.map +1 -0
- package/dist/cjs/pr-review/reviewRunner.js +97 -0
- package/dist/cjs/pr-review/reviewRunner.js.map +1 -0
- package/dist/cjs/pr-review/types.d.ts +80 -0
- package/dist/cjs/pr-review/types.d.ts.map +1 -0
- package/dist/cjs/pr-review/types.js +3 -0
- package/dist/cjs/pr-review/types.js.map +1 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.d.ts +3 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.d.ts.map +1 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.js +114 -0
- package/dist/cjs/pr-review/webhook/WebhookServer.js.map +1 -0
- package/dist/cjs/pr-review/webhook/index.d.ts +2 -0
- package/dist/cjs/pr-review/webhook/index.d.ts.map +1 -0
- package/dist/cjs/pr-review/webhook/index.js +6 -0
- package/dist/cjs/pr-review/webhook/index.js.map +1 -0
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +52 -1
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/mcp/tools.d.ts.map +1 -1
- package/dist/esm/mcp/tools.js +878 -0
- package/dist/esm/mcp/tools.js.map +1 -1
- package/dist/esm/pr-review/PRReviewEngine.d.ts +4 -0
- package/dist/esm/pr-review/PRReviewEngine.d.ts.map +1 -0
- package/dist/esm/pr-review/PRReviewEngine.js +199 -0
- package/dist/esm/pr-review/PRReviewEngine.js.map +1 -0
- package/dist/esm/pr-review/ReviewStore.d.ts +9 -0
- package/dist/esm/pr-review/ReviewStore.d.ts.map +1 -0
- package/dist/esm/pr-review/ReviewStore.js +26 -0
- package/dist/esm/pr-review/ReviewStore.js.map +1 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.d.ts +18 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.js +149 -0
- package/dist/esm/pr-review/adapters/AzureDevOpsAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.d.ts +18 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.js +99 -0
- package/dist/esm/pr-review/adapters/GitHubAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.d.ts +19 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.js +130 -0
- package/dist/esm/pr-review/adapters/GitLabAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.d.ts +14 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.js +2 -0
- package/dist/esm/pr-review/adapters/GitPlatformAdapter.js.map +1 -0
- package/dist/esm/pr-review/adapters/index.d.ts +5 -0
- package/dist/esm/pr-review/adapters/index.d.ts.map +1 -0
- package/dist/esm/pr-review/adapters/index.js +4 -0
- package/dist/esm/pr-review/adapters/index.js.map +1 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.js +151 -0
- package/dist/esm/pr-review/analyzers/QualityGrader.js.map +1 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.js +145 -0
- package/dist/esm/pr-review/analyzers/RegressionDetector.js.map +1 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.js +107 -0
- package/dist/esm/pr-review/analyzers/SecurityScanner.js.map +1 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.d.ts +7 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.js +201 -0
- package/dist/esm/pr-review/analyzers/StaticAnalyzer.js.map +1 -0
- package/dist/esm/pr-review/analyzers/index.d.ts +9 -0
- package/dist/esm/pr-review/analyzers/index.d.ts.map +1 -0
- package/dist/esm/pr-review/analyzers/index.js +5 -0
- package/dist/esm/pr-review/analyzers/index.js.map +1 -0
- package/dist/esm/pr-review/bridge/BrainBridge.d.ts +23 -0
- package/dist/esm/pr-review/bridge/BrainBridge.d.ts.map +1 -0
- package/dist/esm/pr-review/bridge/BrainBridge.js +93 -0
- package/dist/esm/pr-review/bridge/BrainBridge.js.map +1 -0
- package/dist/esm/pr-review/bridge/index.d.ts +2 -0
- package/dist/esm/pr-review/bridge/index.d.ts.map +1 -0
- package/dist/esm/pr-review/bridge/index.js +2 -0
- package/dist/esm/pr-review/bridge/index.js.map +1 -0
- package/dist/esm/pr-review/index.d.ts +5 -0
- package/dist/esm/pr-review/index.d.ts.map +1 -0
- package/dist/esm/pr-review/index.js +3 -0
- package/dist/esm/pr-review/index.js.map +1 -0
- package/dist/esm/pr-review/reviewRunner.d.ts +25 -0
- package/dist/esm/pr-review/reviewRunner.d.ts.map +1 -0
- package/dist/esm/pr-review/reviewRunner.js +92 -0
- package/dist/esm/pr-review/reviewRunner.js.map +1 -0
- package/dist/esm/pr-review/types.d.ts +80 -0
- package/dist/esm/pr-review/types.d.ts.map +1 -0
- package/dist/esm/pr-review/types.js +2 -0
- package/dist/esm/pr-review/types.js.map +1 -0
- package/dist/esm/pr-review/webhook/WebhookServer.d.ts +3 -0
- package/dist/esm/pr-review/webhook/WebhookServer.d.ts.map +1 -0
- package/dist/esm/pr-review/webhook/WebhookServer.js +108 -0
- package/dist/esm/pr-review/webhook/WebhookServer.js.map +1 -0
- package/dist/esm/pr-review/webhook/index.d.ts +2 -0
- package/dist/esm/pr-review/webhook/index.d.ts.map +1 -0
- package/dist/esm/pr-review/webhook/index.js +2 -0
- package/dist/esm/pr-review/webhook/index.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GitLabAdapter = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const PRReviewEngine_1 = require("../PRReviewEngine");
|
|
9
|
+
class GitLabAdapter {
|
|
10
|
+
constructor(token, baseUrl) {
|
|
11
|
+
this.token = token;
|
|
12
|
+
this.baseUrl = baseUrl || "https://gitlab.com/api/v4";
|
|
13
|
+
}
|
|
14
|
+
async validateCredentials() {
|
|
15
|
+
try {
|
|
16
|
+
const res = await axios_1.default.get(`${this.baseUrl}/user`, {
|
|
17
|
+
headers: { "PRIVATE-TOKEN": this.token },
|
|
18
|
+
});
|
|
19
|
+
return res.status === 200;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
getProjectId(owner, repo) {
|
|
26
|
+
return encodeURIComponent(`${owner}/${repo}`);
|
|
27
|
+
}
|
|
28
|
+
async getPRDiff(owner, repo, prNumber) {
|
|
29
|
+
const projectId = this.getProjectId(owner, repo);
|
|
30
|
+
const res = await axios_1.default.get(`${this.baseUrl}/projects/${projectId}/merge_requests/${prNumber}/changes`, {
|
|
31
|
+
headers: { "PRIVATE-TOKEN": this.token },
|
|
32
|
+
});
|
|
33
|
+
const diffs = res.data?.changes || [];
|
|
34
|
+
const diffContent = diffs.map((c) => `diff --git a/${c.old_path} b/${c.new_path}\n${c.diff}`).join("\n");
|
|
35
|
+
return (0, PRReviewEngine_1.parseDiff)(diffContent);
|
|
36
|
+
}
|
|
37
|
+
async getPRMetadata(owner, repo, prNumber) {
|
|
38
|
+
const projectId = this.getProjectId(owner, repo);
|
|
39
|
+
const res = await axios_1.default.get(`${this.baseUrl}/projects/${projectId}/merge_requests/${prNumber}`, {
|
|
40
|
+
headers: { "PRIVATE-TOKEN": this.token },
|
|
41
|
+
});
|
|
42
|
+
const mr = res.data;
|
|
43
|
+
return {
|
|
44
|
+
owner,
|
|
45
|
+
repo,
|
|
46
|
+
prNumber,
|
|
47
|
+
title: mr.title,
|
|
48
|
+
description: mr.description,
|
|
49
|
+
baseBranch: mr.target_branch,
|
|
50
|
+
headBranch: mr.source_branch,
|
|
51
|
+
headSha: mr.diff_refs?.head_sha || "",
|
|
52
|
+
author: mr.author?.username || "unknown",
|
|
53
|
+
createdAt: mr.created_at,
|
|
54
|
+
updatedAt: mr.updated_at,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
async getChangedFiles(owner, repo, prNumber) {
|
|
58
|
+
const projectId = this.getProjectId(owner, repo);
|
|
59
|
+
const res = await axios_1.default.get(`${this.baseUrl}/projects/${projectId}/merge_requests/${prNumber}/changes`, {
|
|
60
|
+
headers: { "PRIVATE-TOKEN": this.token },
|
|
61
|
+
});
|
|
62
|
+
return (res.data?.changes || []).map((c) => c.new_path);
|
|
63
|
+
}
|
|
64
|
+
async getBaseBranch(owner, repo, prNumber) {
|
|
65
|
+
const meta = await this.getPRMetadata(owner, repo, prNumber);
|
|
66
|
+
return meta.baseBranch;
|
|
67
|
+
}
|
|
68
|
+
async postComment(owner, repo, prNumber, body) {
|
|
69
|
+
const projectId = this.getProjectId(owner, repo);
|
|
70
|
+
await axios_1.default.post(`${this.baseUrl}/projects/${projectId}/merge_requests/${prNumber}/notes`, { body }, { headers: { "PRIVATE-TOKEN": this.token } });
|
|
71
|
+
}
|
|
72
|
+
async postReviewComment(owner, repo, prNumber, body, commitId, path, line) {
|
|
73
|
+
const projectId = this.getProjectId(owner, repo);
|
|
74
|
+
const positionData = {
|
|
75
|
+
body,
|
|
76
|
+
position: {
|
|
77
|
+
position_type: "text",
|
|
78
|
+
base_sha: commitId,
|
|
79
|
+
start_sha: commitId,
|
|
80
|
+
head_sha: commitId,
|
|
81
|
+
new_path: path,
|
|
82
|
+
new_line: line,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
await axios_1.default.post(`${this.baseUrl}/projects/${projectId}/merge_requests/${prNumber}/discussions`, positionData, { headers: { "PRIVATE-TOKEN": this.token } });
|
|
86
|
+
}
|
|
87
|
+
async submitReview(owner, repo, prNumber, event, body) {
|
|
88
|
+
const projectId = this.getProjectId(owner, repo);
|
|
89
|
+
const approvalAction = event === "APPROVE" ? "approve" : "unapprove";
|
|
90
|
+
if (event === "APPROVE") {
|
|
91
|
+
await axios_1.default.post(`${this.baseUrl}/projects/${projectId}/merge_requests/${prNumber}/approve`, {}, { headers: { "PRIVATE-TOKEN": this.token } });
|
|
92
|
+
}
|
|
93
|
+
if (body) {
|
|
94
|
+
await this.postComment(owner, repo, prNumber, body);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async setStatus(owner, repo, sha, state, description) {
|
|
98
|
+
const projectId = this.getProjectId(owner, repo);
|
|
99
|
+
const statusMap = {
|
|
100
|
+
pending: "pending",
|
|
101
|
+
success: "success",
|
|
102
|
+
failure: "failed",
|
|
103
|
+
error: "failed",
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
await axios_1.default.post(`${this.baseUrl}/projects/${projectId}/statuses/${sha}`, {
|
|
107
|
+
state: statusMap[state],
|
|
108
|
+
description,
|
|
109
|
+
name: "Lemma PR Review",
|
|
110
|
+
}, { headers: { "PRIVATE-TOKEN": this.token } });
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// GitLab status API may be read-only depending on permissions
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
generateWorkflowYaml(config) {
|
|
117
|
+
return [
|
|
118
|
+
`# GitLab CI - Lemma PR Review`,
|
|
119
|
+
`# Add this to your .gitlab-ci.yml`,
|
|
120
|
+
`lemma-pr-review:`,
|
|
121
|
+
` stage: test`,
|
|
122
|
+
` only:`,
|
|
123
|
+
` - merge_requests`,
|
|
124
|
+
` script:`,
|
|
125
|
+
` - npm install -g @nxuss/lemma`,
|
|
126
|
+
` - lemma pr-review`,
|
|
127
|
+
` variables:`,
|
|
128
|
+
` LEMMA_LICENSE_KEY: ${"$"}{LEMMA_LICENSE_KEY}`,
|
|
129
|
+
` LEMMA_PLATFORM: gitlab`,
|
|
130
|
+
` LEMMA_REPO: ${"$"}{CI_PROJECT_PATH}`,
|
|
131
|
+
` LEMMA_PR_NUMBER: ${"$"}{CI_MERGE_REQUEST_IID}`,
|
|
132
|
+
` GITLAB_TOKEN: ${"$"}{GITLAB_TOKEN}`,
|
|
133
|
+
].join("\n");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.GitLabAdapter = GitLabAdapter;
|
|
137
|
+
//# sourceMappingURL=GitLabAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitLabAdapter.js","sourceRoot":"","sources":["../../../../src/pr-review/adapters/GitLabAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DiffFile, PRMetadata, ReviewEvent, StatusState, WorkflowConfig } from "../types";
|
|
2
|
+
export interface GitPlatformAdapter {
|
|
3
|
+
validateCredentials(): Promise<boolean>;
|
|
4
|
+
getPRDiff(owner: string, repo: string, prNumber: number): Promise<DiffFile[]>;
|
|
5
|
+
getPRMetadata(owner: string, repo: string, prNumber: number): Promise<PRMetadata>;
|
|
6
|
+
getChangedFiles(owner: string, repo: string, prNumber: number): Promise<string[]>;
|
|
7
|
+
getBaseBranch(owner: string, repo: string, prNumber: number): Promise<string>;
|
|
8
|
+
postComment(owner: string, repo: string, prNumber: number, body: string): Promise<void>;
|
|
9
|
+
postReviewComment(owner: string, repo: string, prNumber: number, body: string, commitId: string, path: string, line: number): Promise<void>;
|
|
10
|
+
submitReview(owner: string, repo: string, prNumber: number, event: ReviewEvent, body: string): Promise<void>;
|
|
11
|
+
setStatus(owner: string, repo: string, sha: string, state: StatusState, description: string): Promise<void>;
|
|
12
|
+
generateWorkflowYaml(config: WorkflowConfig): string;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=GitPlatformAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitPlatformAdapter.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/adapters/GitPlatformAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1F,MAAM,WAAW,kBAAkB;IACjC,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9E,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAClF,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9E,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxF,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5I,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7G,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5G,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAAC;CACtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitPlatformAdapter.js","sourceRoot":"","sources":["../../../../src/pr-review/adapters/GitPlatformAdapter.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitLabAdapter = exports.AzureDevOpsAdapter = exports.GitHubAdapter = void 0;
|
|
4
|
+
var GitHubAdapter_1 = require("./GitHubAdapter");
|
|
5
|
+
Object.defineProperty(exports, "GitHubAdapter", { enumerable: true, get: function () { return GitHubAdapter_1.GitHubAdapter; } });
|
|
6
|
+
var AzureDevOpsAdapter_1 = require("./AzureDevOpsAdapter");
|
|
7
|
+
Object.defineProperty(exports, "AzureDevOpsAdapter", { enumerable: true, get: function () { return AzureDevOpsAdapter_1.AzureDevOpsAdapter; } });
|
|
8
|
+
var GitLabAdapter_1 = require("./GitLabAdapter");
|
|
9
|
+
Object.defineProperty(exports, "GitLabAdapter", { enumerable: true, get: function () { return GitLabAdapter_1.GitLabAdapter; } });
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/pr-review/adapters/index.ts"],"names":[],"mappings":";;;AACA,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAC3B,iDAAgD;AAAvC,8GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Finding, DiffFile } from "../types";
|
|
2
|
+
export interface QualityAnalysisResult {
|
|
3
|
+
findings: Finding[];
|
|
4
|
+
score: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function analyzeQuality(diffFiles: DiffFile[], workspaceRoot: string): QualityAnalysisResult;
|
|
7
|
+
//# sourceMappingURL=QualityGrader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QualityGrader.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/analyzers/QualityGrader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AA4B7C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,qBAAqB,CAiJlG"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyzeQuality = analyzeQuality;
|
|
4
|
+
function findTestFiles(diffFiles, workspaceRoot) {
|
|
5
|
+
const testPatterns = [/\.test\.(ts|tsx|js|jsx)$/, /\.spec\.(ts|tsx|js|jsx)$/, /__tests__\//];
|
|
6
|
+
const testFiles = diffFiles
|
|
7
|
+
.filter(df => testPatterns.some(p => p.test(df.path)))
|
|
8
|
+
.map(df => df.path);
|
|
9
|
+
const sourceFiles = diffFiles
|
|
10
|
+
.filter(df => df.path.match(/\.(ts|tsx)$/) && !testPatterns.some(p => p.test(df.path)) && df.status !== "deleted")
|
|
11
|
+
.map(df => df.path);
|
|
12
|
+
const hasTestCoverage = sourceFiles.every(src => {
|
|
13
|
+
const baseName = src.replace(/\.(ts|tsx)$/, "");
|
|
14
|
+
return testFiles.some(tf => tf.includes(baseName));
|
|
15
|
+
});
|
|
16
|
+
if (!hasTestCoverage && sourceFiles.length > 0) {
|
|
17
|
+
const uncovered = sourceFiles.filter(src => {
|
|
18
|
+
const baseName = src.replace(/\.(ts|tsx)$/, "");
|
|
19
|
+
return !testFiles.some(tf => tf.includes(baseName));
|
|
20
|
+
});
|
|
21
|
+
return uncovered;
|
|
22
|
+
}
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
function analyzeQuality(diffFiles, workspaceRoot) {
|
|
26
|
+
const findings = [];
|
|
27
|
+
let totalScore = 100;
|
|
28
|
+
const hasTests = diffFiles.some(df => /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(df.path) || /__tests__\//.test(df.path));
|
|
29
|
+
const modifiedSourceFiles = diffFiles.filter(df => df.path.match(/\.(ts|tsx)$/) && df.status !== "deleted");
|
|
30
|
+
if (!hasTests && modifiedSourceFiles.length > 0) {
|
|
31
|
+
const uncovered = findTestFiles(diffFiles, workspaceRoot);
|
|
32
|
+
for (const file of uncovered) {
|
|
33
|
+
findings.push({
|
|
34
|
+
ruleId: "quality-no-tests",
|
|
35
|
+
severity: "HIGH",
|
|
36
|
+
category: "quality",
|
|
37
|
+
filePath: file,
|
|
38
|
+
message: `No test file found for modified source file`,
|
|
39
|
+
detail: `Changes to source files should be accompanied by corresponding tests.`,
|
|
40
|
+
suggestion: `Create a test file at ${file.replace(/\.(ts|tsx)$/, ".test.ts")}`,
|
|
41
|
+
score: -10,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
for (const df of diffFiles) {
|
|
46
|
+
if (!df.content)
|
|
47
|
+
continue;
|
|
48
|
+
if (df.status === "deleted")
|
|
49
|
+
continue;
|
|
50
|
+
const lines = df.content.split("\n");
|
|
51
|
+
for (let i = 0; i < lines.length; i++) {
|
|
52
|
+
const line = lines[i];
|
|
53
|
+
const lineNum = i + 1;
|
|
54
|
+
const debugMatch = line.match(/^\s*console\.(log|debug|info)\(/);
|
|
55
|
+
if (debugMatch) {
|
|
56
|
+
findings.push({
|
|
57
|
+
ruleId: "quality-console-log",
|
|
58
|
+
severity: "MEDIUM",
|
|
59
|
+
category: "quality",
|
|
60
|
+
filePath: df.path,
|
|
61
|
+
line: lineNum,
|
|
62
|
+
message: `console.${debugMatch[1]}() left in code`,
|
|
63
|
+
detail: `Debugging statements should be removed before committing.`,
|
|
64
|
+
suggestion: `Remove this console statement or replace with a proper logger if needed for production.`,
|
|
65
|
+
score: -5,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (line.includes("debugger;") || line.match(/^\s*debugger\s*;?$/)) {
|
|
69
|
+
findings.push({
|
|
70
|
+
ruleId: "quality-debugger",
|
|
71
|
+
severity: "HIGH",
|
|
72
|
+
category: "quality",
|
|
73
|
+
filePath: df.path,
|
|
74
|
+
line: lineNum,
|
|
75
|
+
message: `"debugger" statement found in code`,
|
|
76
|
+
detail: `Debugger statements will halt execution in development tools.`,
|
|
77
|
+
suggestion: `Remove the debugger statement before committing.`,
|
|
78
|
+
score: -10,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const magicNumberMatch = line.match(/(?<!\w)(\d{4,})(?!\w)/);
|
|
82
|
+
if (magicNumberMatch && !line.trim().startsWith("//") && !line.trim().startsWith("*")) {
|
|
83
|
+
const isLikelyMagic = !line.includes("const ") && !line.includes("let ") && !line.includes("import ") && !line.match(/\.\d{4}/);
|
|
84
|
+
if (isLikelyMagic && !df.path.match(/\.(json|css|scss|less|config\.(ts|js))$/)) {
|
|
85
|
+
findings.push({
|
|
86
|
+
ruleId: "quality-magic-number",
|
|
87
|
+
severity: "LOW",
|
|
88
|
+
category: "quality",
|
|
89
|
+
filePath: df.path,
|
|
90
|
+
line: lineNum,
|
|
91
|
+
message: `Magic number ${magicNumberMatch[1]} found`,
|
|
92
|
+
detail: `Hardcoded numbers reduce code readability and maintainability.`,
|
|
93
|
+
suggestion: `Extract "${magicNumberMatch[1]}" into a named constant.`,
|
|
94
|
+
score: -2,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const commentedCodeMatch = line.match(/^\s*\/\/\s*(function|class|const|let|var|if|for|while|return)\s/);
|
|
99
|
+
if (commentedCodeMatch) {
|
|
100
|
+
findings.push({
|
|
101
|
+
ruleId: "quality-commented-code",
|
|
102
|
+
severity: "LOW",
|
|
103
|
+
category: "quality",
|
|
104
|
+
filePath: df.path,
|
|
105
|
+
line: lineNum,
|
|
106
|
+
message: `Commented-out code detected`,
|
|
107
|
+
detail: `Commented code creates noise and can become outdated.`,
|
|
108
|
+
suggestion: `Remove dead code instead of commenting it out. Use version control for history.`,
|
|
109
|
+
score: -2,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (df.path.match(/\.(ts|tsx)$/)) {
|
|
114
|
+
const pascalCaseType = /^[A-Z][a-z]\w+/;
|
|
115
|
+
const linesForNaming = df.content.split("\n");
|
|
116
|
+
for (let i = 0; i < linesForNaming.length; i++) {
|
|
117
|
+
const line = linesForNaming[i];
|
|
118
|
+
const lineNum = i + 1;
|
|
119
|
+
const interfaceMatch = line.match(/^interface\s+(\w+)/);
|
|
120
|
+
if (interfaceMatch && !pascalCaseType.test(interfaceMatch[1])) {
|
|
121
|
+
findings.push({
|
|
122
|
+
ruleId: "quality-naming-interface",
|
|
123
|
+
severity: "LOW",
|
|
124
|
+
category: "quality",
|
|
125
|
+
filePath: df.path,
|
|
126
|
+
line: lineNum,
|
|
127
|
+
message: `Interface "${interfaceMatch[1]}" should use PascalCase`,
|
|
128
|
+
detail: `TypeScript convention: interfaces use PascalCase.`,
|
|
129
|
+
suggestion: `Rename "${interfaceMatch[1]}" to "${interfaceMatch[1].charAt(0).toUpperCase() + interfaceMatch[1].slice(1)}"`,
|
|
130
|
+
score: -2,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const typeAliasMatch = line.match(/^type\s+(\w+)/);
|
|
134
|
+
if (typeAliasMatch && !pascalCaseType.test(typeAliasMatch[1])) {
|
|
135
|
+
findings.push({
|
|
136
|
+
ruleId: "quality-naming-type",
|
|
137
|
+
severity: "LOW",
|
|
138
|
+
category: "quality",
|
|
139
|
+
filePath: df.path,
|
|
140
|
+
line: lineNum,
|
|
141
|
+
message: `Type alias "${typeAliasMatch[1]}" should use PascalCase`,
|
|
142
|
+
detail: `TypeScript convention: type aliases use PascalCase.`,
|
|
143
|
+
suggestion: `Rename "${typeAliasMatch[1]}" to "${typeAliasMatch[1].charAt(0).toUpperCase() + typeAliasMatch[1].slice(1)}"`,
|
|
144
|
+
score: -2,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const deduction = findings.reduce((sum, f) => sum + Math.abs(f.score), 0);
|
|
151
|
+
totalScore = Math.max(0, Math.min(100, totalScore - deduction));
|
|
152
|
+
return { findings, score: totalScore };
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=QualityGrader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QualityGrader.js","sourceRoot":"","sources":["../../../../src/pr-review/analyzers/QualityGrader.ts"],"names":[],"mappings":";;AAiCA,wCAiJC;AAhLD,SAAS,aAAa,CAAC,SAAqB,EAAE,aAAqB;IACjE,MAAM,YAAY,GAAG,CAAC,0BAA0B,EAAE,0BAA0B,EAAE,aAAa,CAAC,CAAC;IAC7F,MAAM,SAAS,GAAG,SAAS;SACxB,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;SACrD,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAEtB,MAAM,WAAW,GAAG,SAAS;SAC1B,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,CAAC;SACjH,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAEtB,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;QAC9C,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QAChD,OAAO,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,eAAe,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;YACzC,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAChD,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAOD,SAAgB,cAAc,CAAC,SAAqB,EAAE,aAAqB;IACzE,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,UAAU,GAAG,GAAG,CAAC;IAErB,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CACnC,iCAAiC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAC/E,CAAC;IAEF,MAAM,mBAAmB,GAAG,SAAS,CAAC,MAAM,CAC1C,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,CAC9D,CAAC;IAEF,IAAI,CAAC,QAAQ,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;QAC1D,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,kBAAkB;gBAC1B,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,6CAA6C;gBACtD,MAAM,EAAE,uEAAuE;gBAC/E,UAAU,EAAE,yBAAyB,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,UAAU,CAAC,EAAE;gBAC9E,KAAK,EAAE,CAAC,EAAE;aACX,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,EAAE,CAAC,OAAO;YAAE,SAAS;QAC1B,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS;YAAE,SAAS;QAEtC,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;YAEtB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACjE,IAAI,UAAU,EAAE,CAAC;gBACf,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,qBAAqB;oBAC7B,QAAQ,EAAE,QAAQ;oBAClB,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,WAAW,UAAU,CAAC,CAAC,CAAC,iBAAiB;oBAClD,MAAM,EAAE,2DAA2D;oBACnE,UAAU,EAAE,yFAAyF;oBACrG,KAAK,EAAE,CAAC,CAAC;iBACV,CAAC,CAAC;YACL,CAAC;YAED,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBACnE,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,kBAAkB;oBAC1B,QAAQ,EAAE,MAAM;oBAChB,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,oCAAoC;oBAC7C,MAAM,EAAE,+DAA+D;oBACvE,UAAU,EAAE,kDAAkD;oBAC9D,KAAK,EAAE,CAAC,EAAE;iBACX,CAAC,CAAC;YACL,CAAC;YAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAC7D,IAAI,gBAAgB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtF,MAAM,aAAa,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBAChI,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,EAAE,CAAC;oBAC/E,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,sBAAsB;wBAC9B,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,SAAS;wBACnB,QAAQ,EAAE,EAAE,CAAC,IAAI;wBACjB,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,gBAAgB,gBAAgB,CAAC,CAAC,CAAC,QAAQ;wBACpD,MAAM,EAAE,gEAAgE;wBACxE,UAAU,EAAE,YAAY,gBAAgB,CAAC,CAAC,CAAC,0BAA0B;wBACrE,KAAK,EAAE,CAAC,CAAC;qBACV,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,iEAAiE,CAAC,CAAC;YACzG,IAAI,kBAAkB,EAAE,CAAC;gBACvB,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,wBAAwB;oBAChC,QAAQ,EAAE,KAAK;oBACf,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,EAAE,CAAC,IAAI;oBACjB,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,6BAA6B;oBACtC,MAAM,EAAE,uDAAuD;oBAC/D,UAAU,EAAE,iFAAiF;oBAC7F,KAAK,EAAE,CAAC,CAAC;iBACV,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YACjC,MAAM,cAAc,GAAG,gBAAgB,CAAC;YACxC,MAAM,cAAc,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;gBAC/B,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;gBAEtB,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;gBACxD,IAAI,cAAc,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC9D,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,0BAA0B;wBAClC,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,SAAS;wBACnB,QAAQ,EAAE,EAAE,CAAC,IAAI;wBACjB,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,cAAc,cAAc,CAAC,CAAC,CAAC,yBAAyB;wBACjE,MAAM,EAAE,mDAAmD;wBAC3D,UAAU,EAAE,WAAW,cAAc,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;wBAC1H,KAAK,EAAE,CAAC,CAAC;qBACV,CAAC,CAAC;gBACL,CAAC;gBAED,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;gBACnD,IAAI,cAAc,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC9D,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,qBAAqB;wBAC7B,QAAQ,EAAE,KAAK;wBACf,QAAQ,EAAE,SAAS;wBACnB,QAAQ,EAAE,EAAE,CAAC,IAAI;wBACjB,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,eAAe,cAAc,CAAC,CAAC,CAAC,yBAAyB;wBAClE,MAAM,EAAE,qDAAqD;wBAC7D,UAAU,EAAE,WAAW,cAAc,CAAC,CAAC,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;wBAC1H,KAAK,EAAE,CAAC,CAAC;qBACV,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC;IAEhE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Finding, DiffFile } from "../types";
|
|
2
|
+
export interface RegressionAnalysisResult {
|
|
3
|
+
findings: Finding[];
|
|
4
|
+
score: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function analyzeRegression(diffFiles: DiffFile[], workspaceRoot: string, baseBranch?: string): RegressionAnalysisResult;
|
|
7
|
+
//# sourceMappingURL=RegressionDetector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegressionDetector.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/analyzers/RegressionDetector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,QAAQ,EAAE,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,GAAE,MAAe,GAC1B,wBAAwB,CAoJ1B"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.analyzeRegression = analyzeRegression;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
function analyzeRegression(diffFiles, workspaceRoot, baseBranch = "main") {
|
|
10
|
+
const findings = [];
|
|
11
|
+
let totalScore = 100;
|
|
12
|
+
const addedOrModified = diffFiles.filter(df => df.status === "added" || df.status === "modified");
|
|
13
|
+
if (addedOrModified.length === 0) {
|
|
14
|
+
return { findings, score: totalScore };
|
|
15
|
+
}
|
|
16
|
+
const allFiles = new Set(addedOrModified.map(df => df.path));
|
|
17
|
+
try {
|
|
18
|
+
const since = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString().split("T")[0];
|
|
19
|
+
let gitLog = "";
|
|
20
|
+
try {
|
|
21
|
+
gitLog = (0, child_process_1.execSync)(`git log --since="${since}" --name-only --pretty=format:"COMMIT:%H" --diff-filter=M`, { cwd: workspaceRoot, encoding: "utf8", timeout: 10000 });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { findings, score: totalScore };
|
|
25
|
+
}
|
|
26
|
+
const fileChurn = new Map();
|
|
27
|
+
const coChangeMap = new Map();
|
|
28
|
+
let currentGroup = [];
|
|
29
|
+
for (const line of gitLog.split("\n")) {
|
|
30
|
+
const trimmed = line.trim();
|
|
31
|
+
if (trimmed.startsWith("COMMIT:")) {
|
|
32
|
+
currentGroup = [];
|
|
33
|
+
}
|
|
34
|
+
else if (trimmed && !trimmed.startsWith("COMMIT:")) {
|
|
35
|
+
currentGroup.push(trimmed);
|
|
36
|
+
fileChurn.set(trimmed, (fileChurn.get(trimmed) || 0) + 1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
for (const filePath of allFiles) {
|
|
40
|
+
const churn = fileChurn.get(filePath) || 0;
|
|
41
|
+
if (churn >= 10) {
|
|
42
|
+
findings.push({
|
|
43
|
+
ruleId: "reg-high-churn",
|
|
44
|
+
severity: "HIGH",
|
|
45
|
+
category: "regression",
|
|
46
|
+
filePath,
|
|
47
|
+
message: `High churn rate (${churn}x in 30 days) — statistically risky file`,
|
|
48
|
+
detail: `Files that change frequently have higher probability of introducing regressions.`,
|
|
49
|
+
suggestion: `Consider refactoring this file into smaller, more stable modules. Investigate why it changes so often.`,
|
|
50
|
+
score: -10,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else if (churn >= 5) {
|
|
54
|
+
findings.push({
|
|
55
|
+
ruleId: "reg-moderate-churn",
|
|
56
|
+
severity: "MEDIUM",
|
|
57
|
+
category: "regression",
|
|
58
|
+
filePath,
|
|
59
|
+
message: `Moderate churn rate (${churn}x in 30 days)`,
|
|
60
|
+
detail: `This file has been modified multiple times recently.`,
|
|
61
|
+
suggestion: `Review changes carefully for regressions. Consider if this file needs stabilization.`,
|
|
62
|
+
score: -5,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const addedExports = new Map();
|
|
67
|
+
const deletedExports = new Map();
|
|
68
|
+
for (const df of addedOrModified) {
|
|
69
|
+
if (!df.patch || !df.path.match(/\.(ts|tsx)$/))
|
|
70
|
+
continue;
|
|
71
|
+
const patchLines = df.patch.split("\n");
|
|
72
|
+
const addedDeclarations = [];
|
|
73
|
+
const removedDeclarations = [];
|
|
74
|
+
for (const pl of patchLines) {
|
|
75
|
+
const exportMatch = pl.match(/^\+.*\bexport\s+(?:function|class|interface|type|const|enum|default)\s+(\w+)/);
|
|
76
|
+
if (exportMatch)
|
|
77
|
+
addedDeclarations.push(exportMatch[1]);
|
|
78
|
+
const removedMatch = pl.match(/^-.*\bexport\s+(?:function|class|interface|type|const|enum|default)\s+(\w+)/);
|
|
79
|
+
if (removedMatch)
|
|
80
|
+
removedDeclarations.push(removedMatch[1]);
|
|
81
|
+
}
|
|
82
|
+
if (addedDeclarations.length > 0)
|
|
83
|
+
addedExports.set(df.path, addedDeclarations);
|
|
84
|
+
if (removedDeclarations.length > 0)
|
|
85
|
+
deletedExports.set(df.path, removedDeclarations);
|
|
86
|
+
}
|
|
87
|
+
if (deletedExports.size > 0) {
|
|
88
|
+
const importsToCheck = new Map();
|
|
89
|
+
function walkDir(dir, rel) {
|
|
90
|
+
try {
|
|
91
|
+
const entries = require("fs").readdirSync(dir, { withFileTypes: true });
|
|
92
|
+
for (const e of entries) {
|
|
93
|
+
if (["node_modules", ".git", "dist", "chroma_data", ".lemma"].includes(e.name))
|
|
94
|
+
continue;
|
|
95
|
+
const abs = path_1.default.join(dir, e.name);
|
|
96
|
+
const relPath = rel ? path_1.default.join(rel, e.name) : e.name;
|
|
97
|
+
if (e.isDirectory())
|
|
98
|
+
walkDir(abs, relPath);
|
|
99
|
+
else if (e.name.match(/\.(ts|tsx)$/) && !e.name.endsWith(".d.ts")) {
|
|
100
|
+
try {
|
|
101
|
+
const content = require("fs").readFileSync(abs, "utf8");
|
|
102
|
+
const importMatches = content.matchAll(/import\s+(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+["']([^"']+)["']/g);
|
|
103
|
+
for (const im of importMatches) {
|
|
104
|
+
if (!importsToCheck.has(im[1]))
|
|
105
|
+
importsToCheck.set(im[1], []);
|
|
106
|
+
importsToCheck.get(im[1]).push(relPath);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch { }
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch { }
|
|
114
|
+
}
|
|
115
|
+
walkDir(workspaceRoot, "");
|
|
116
|
+
for (const [filePath, removed] of deletedExports) {
|
|
117
|
+
const relativePath = path_1.default.relative(workspaceRoot, filePath).replace(/\\/g, "/");
|
|
118
|
+
const moduleName = relativePath.replace(/\.(ts|tsx)$/, "");
|
|
119
|
+
const consumers = importsToCheck.get(moduleName) || importsToCheck.get("./" + moduleName) || [];
|
|
120
|
+
const removedNames = removed.filter(name => consumers.some(consumerPath => {
|
|
121
|
+
try {
|
|
122
|
+
const consumerContent = require("fs").readFileSync(path_1.default.join(workspaceRoot, consumerPath), "utf8");
|
|
123
|
+
return consumerContent.includes(name);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
}));
|
|
129
|
+
if (removedNames.length > 0) {
|
|
130
|
+
findings.push({
|
|
131
|
+
ruleId: "reg-breaking-change",
|
|
132
|
+
severity: "CRITICAL",
|
|
133
|
+
category: "regression",
|
|
134
|
+
filePath: relativePath,
|
|
135
|
+
message: `Breaking change: removed export(s) "${removedNames.join(", ")}" used by other modules`,
|
|
136
|
+
detail: `Removing these exports will break consumers. Files affected: ${consumers.join(", ")}`,
|
|
137
|
+
suggestion: `Add deprecation warnings before removal, or update all consumers in the same PR.`,
|
|
138
|
+
score: -15,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return { findings, score: totalScore };
|
|
146
|
+
}
|
|
147
|
+
const deduction = findings.reduce((sum, f) => sum + Math.abs(f.score), 0);
|
|
148
|
+
totalScore = Math.max(0, Math.min(100, totalScore - deduction));
|
|
149
|
+
return { findings, score: totalScore };
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=RegressionDetector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RegressionDetector.js","sourceRoot":"","sources":["../../../../src/pr-review/analyzers/RegressionDetector.ts"],"names":[],"mappings":";;;;;AASA,8CAwJC;AAjKD,iDAAyC;AACzC,gDAAwB;AAQxB,SAAgB,iBAAiB,CAC/B,SAAqB,EACrB,aAAqB,EACrB,aAAqB,MAAM;IAE3B,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,UAAU,GAAG,GAAG,CAAC;IAErB,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC;IAClG,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAE7D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1F,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,MAAM,GAAG,IAAA,wBAAQ,EACf,oBAAoB,KAAK,2DAA2D,EACpF,EAAE,GAAG,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CACzD,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QACzC,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;QACnD,IAAI,YAAY,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAClC,YAAY,GAAG,EAAE,CAAC;YACpB,CAAC;iBAAM,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrD,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC3B,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;gBAChB,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,gBAAgB;oBACxB,QAAQ,EAAE,MAAM;oBAChB,QAAQ,EAAE,YAAY;oBACtB,QAAQ;oBACR,OAAO,EAAE,oBAAoB,KAAK,0CAA0C;oBAC5E,MAAM,EAAE,kFAAkF;oBAC1F,UAAU,EAAE,wGAAwG;oBACpH,KAAK,EAAE,CAAC,EAAE;iBACX,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC;oBACZ,MAAM,EAAE,oBAAoB;oBAC5B,QAAQ,EAAE,QAAQ;oBAClB,QAAQ,EAAE,YAAY;oBACtB,QAAQ;oBACR,OAAO,EAAE,wBAAwB,KAAK,eAAe;oBACrD,MAAM,EAAE,sDAAsD;oBAC9D,UAAU,EAAE,sFAAsF;oBAClG,KAAK,EAAE,CAAC,CAAC;iBACV,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;QACjD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAoB,CAAC;QAEnD,KAAK,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC;YACjC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;gBAAE,SAAS;YACzD,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxC,MAAM,iBAAiB,GAAa,EAAE,CAAC;YACvC,MAAM,mBAAmB,GAAa,EAAE,CAAC;YAEzC,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;gBAC5B,MAAM,WAAW,GAAG,EAAE,CAAC,KAAK,CAAC,8EAA8E,CAAC,CAAC;gBAC7G,IAAI,WAAW;oBAAE,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;gBAExD,MAAM,YAAY,GAAG,EAAE,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;gBAC7G,IAAI,YAAY;oBAAE,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,CAAC;YAED,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC;gBAAE,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC/E,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC;gBAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,cAAc,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,cAAc,GAAG,IAAI,GAAG,EAAoB,CAAC;YAEnD,SAAS,OAAO,CAAC,GAAW,EAAE,GAAW;gBACvC,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;oBACxE,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;wBACxB,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;4BAAE,SAAS;wBACzF,MAAM,GAAG,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;wBACnC,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;wBACtD,IAAI,CAAC,CAAC,WAAW,EAAE;4BAAE,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;6BACtC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;4BAClE,IAAI,CAAC;gCACH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gCACxD,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,qEAAqE,CAAC,CAAC;gCAC9G,KAAK,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC;oCAC/B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;wCAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oCAC9D,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gCAC3C,CAAC;4BACH,CAAC;4BAAC,MAAM,CAAC,CAAA,CAAC;wBACZ,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACZ,CAAC;YAED,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAE3B,KAAK,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;gBACjD,MAAM,YAAY,GAAG,cAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAChF,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;gBAC3D,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;gBAChG,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CACzC,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;oBAC5B,IAAI,CAAC;wBACH,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,CAChD,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,MAAM,CAC/C,CAAC;wBACF,OAAO,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACxC,CAAC;oBAAC,MAAM,CAAC;wBAAC,OAAO,KAAK,CAAC;oBAAC,CAAC;gBAC3B,CAAC,CAAC,CACH,CAAC;gBAEF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5B,QAAQ,CAAC,IAAI,CAAC;wBACZ,MAAM,EAAE,qBAAqB;wBAC7B,QAAQ,EAAE,UAAU;wBACpB,QAAQ,EAAE,YAAY;wBACtB,QAAQ,EAAE,YAAY;wBACtB,OAAO,EAAE,uCAAuC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB;wBAChG,MAAM,EAAE,gEAAgE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;wBAC9F,UAAU,EAAE,kFAAkF;wBAC9F,KAAK,EAAE,CAAC,EAAE;qBACX,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC;IAEhE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Finding, DiffFile } from "../types";
|
|
2
|
+
export interface SecurityAnalysisResult {
|
|
3
|
+
findings: Finding[];
|
|
4
|
+
score: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function analyzeSecurity(diffFiles: DiffFile[]): SecurityAnalysisResult;
|
|
7
|
+
//# sourceMappingURL=SecurityScanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecurityScanner.d.ts","sourceRoot":"","sources":["../../../../src/pr-review/analyzers/SecurityScanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAiC7C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,sBAAsB,CAwF7E"}
|