job51-gitlab-cr-node-jt-1 2.3.7 → 2.3.9
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/.claude/rules/code-review-rules.md +9 -0
- package/index.js +37 -14
- package/package.json +1 -1
|
@@ -241,6 +241,11 @@
|
|
|
241
241
|
|
|
242
242
|
18. **输出格式**:严格参照 SKILL.md 模板,无某类问题时省略对应部分;
|
|
243
243
|
> - **必须输出 `<LINE_INFO>` 标签**:包含所有问题的行号信息
|
|
244
|
+
> - **LINE_INFO 输出约束**(关键规则):
|
|
245
|
+
> - **仅有存在严重问题时,才允许在 LINE_INFO 中输出行号数据**
|
|
246
|
+
> - **无严重问题时,LINE_INFO 必须输出空数组 `[]`**
|
|
247
|
+
> - **禁止在无严重问题时输出行号数据**
|
|
248
|
+
> - 示例:无问题时输出 `<LINE_INFO>[]</LINE_INFO>`,不得输出具体行号
|
|
244
249
|
> - **LINE_INFO 格式**(与 targetLine 结构一致):
|
|
245
250
|
```json
|
|
246
251
|
[{"new_path":"文件路径","new_line":行号,"old_path":"文件路径","old_line":行号}]
|
|
@@ -277,3 +282,7 @@
|
|
|
277
282
|
> - **禁止编造 diff 中没有的代码**,如报告中不得出现 diff 中完全不存在的条件判断、方法调用等
|
|
278
283
|
> - **验证方法**:将错误代码示例与 diff 内容逐行对比,确认每行代码都能对应上
|
|
279
284
|
> - [ ] **最终自检**:如果这段代码是安全的/正确的,我为什么要报告它?如无法回答,省略该问题
|
|
285
|
+
> - [ ] **LINE_INFO 输出验证**(关键规则):
|
|
286
|
+
> - **仅在有严重问题时,才允许在 LINE_INFO 中输出行号数据**
|
|
287
|
+
> - **无严重问题时,LINE_INFO 必须输出 `[]`**
|
|
288
|
+
> - **输出前检查**:是否有"🔴 严重问题"标题?如无,则 LINE_INFO 必须为空数组
|
package/index.js
CHANGED
|
@@ -73,6 +73,10 @@ class GitLabCodeReviewer {
|
|
|
73
73
|
|
|
74
74
|
debugLog(`本地 AI 命令审核完成,AI 审核结果长度:${claudeResult?.length || 0}`);
|
|
75
75
|
|
|
76
|
+
// 打印报告内容前 500 字符(避免过长)
|
|
77
|
+
const reportPreview = claudeResult?.length > 500 ? claudeResult.substring(0, 500) + '...' : claudeResult;
|
|
78
|
+
debugLog(`AI 审核报告内容预览:${reportPreview}`);
|
|
79
|
+
|
|
76
80
|
// 使用正则提取 LINE_INFO 内容(支持换行)
|
|
77
81
|
const lineInfoMatch = claudeResult?.match(/<LINE_INFO>\s*\[([^\]]*)\]\s*<\/LINE_INFO>/);
|
|
78
82
|
const hasLineInfoTag = lineInfoMatch !== null && lineInfoMatch !== undefined;
|
|
@@ -81,33 +85,40 @@ class GitLabCodeReviewer {
|
|
|
81
85
|
const lineInfoContent = hasLineInfoTag ? lineInfoMatch[1].replace(/\s/g, '') : '';
|
|
82
86
|
const hasNonEmptyLineInfo = hasLineInfoTag && lineInfoContent !== '';
|
|
83
87
|
|
|
84
|
-
|
|
88
|
+
debugLog(`LINE_INFO 检查结果:hasLineInfoTag=${hasLineInfoTag}, hasNonEmptyLineInfo=${hasNonEmptyLineInfo}, lineInfoContent=[${lineInfoContent}]`);
|
|
89
|
+
|
|
90
|
+
// LINE_INFO 为空或不存在 → 说明无问题,直接返回标准空格式
|
|
85
91
|
if (!hasLineInfoTag || !hasNonEmptyLineInfo) {
|
|
86
|
-
debugLog(
|
|
87
|
-
return { reportContent:
|
|
92
|
+
debugLog(`【决策】LINE_INFO 为空或不存在,说明无问题,直接返回标准空格式`);
|
|
93
|
+
return { reportContent: '<REPORT>\n## 🤖 AI 代码审查结果\n\n</REPORT>', lineInfo: '[]' };
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
// LINE_INFO 有行号 → 继续检查报告内容
|
|
91
97
|
// 先检查是否有严重问题(放宽匹配,只检查"严重问题"关键词)
|
|
92
98
|
const hasSeriousProblem = claudeResult && claudeResult.includes('严重问题');
|
|
93
99
|
|
|
100
|
+
debugLog(`严重问题检查:hasSeriousProblem=${hasSeriousProblem}`);
|
|
101
|
+
|
|
94
102
|
// 无严重问题 → 直接返回标准空格式
|
|
95
103
|
if (!hasSeriousProblem) {
|
|
96
|
-
debugLog(
|
|
104
|
+
debugLog(`【决策】报告无严重问题,返回标准空格式`);
|
|
97
105
|
return { reportContent: claudeResult, lineInfo: lineInfoContent };
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
// 有严重问题 → 检查标题是否符合要求
|
|
101
109
|
const hasValidTitle = claudeResult && claudeResult.includes('🤖 AI 代码审查结果');
|
|
110
|
+
|
|
111
|
+
debugLog(`标题检查:hasValidTitle=${hasValidTitle}`);
|
|
112
|
+
|
|
102
113
|
if (hasValidTitle) {
|
|
103
|
-
debugLog(
|
|
114
|
+
debugLog(`【决策】报告包含严重问题且标题正确,接受结果 (尝试 ${attempts})`);
|
|
104
115
|
return extractReportContent(claudeResult);
|
|
105
116
|
}
|
|
106
117
|
|
|
107
118
|
// 有严重问题但标题不符合 → 重试
|
|
108
|
-
debugLog(
|
|
119
|
+
debugLog(`【决策】报告包含严重问题但标题不符合要求 (尝试 ${attempts}),将重试...`);
|
|
109
120
|
if (attempts >= maxAttempts) {
|
|
110
|
-
debugLog(
|
|
121
|
+
debugLog(`【决策】已达到最大重试次数 ${maxAttempts},返回最后一次结果`);
|
|
111
122
|
return extractReportContent(claudeResult);
|
|
112
123
|
}
|
|
113
124
|
} catch (error) {
|
|
@@ -251,9 +262,14 @@ ${diffObject.diff}`;
|
|
|
251
262
|
//若结果为空,则记录日志
|
|
252
263
|
if (!claudeResult) {
|
|
253
264
|
debugLog(`本地AI命令审核结果为空`);
|
|
265
|
+
return { reportContent: claudeResult || '<REPORT>\n## 🤖 AI 代码审查结果\n\n</REPORT>', lineInfo: '[]' };
|
|
254
266
|
}
|
|
255
267
|
debugLog(`本地 AI 命令审核完成,审核结果长度:${claudeResult?.length || 0}`);
|
|
256
268
|
|
|
269
|
+
// 打印报告内容前 500 字符(避免过长)
|
|
270
|
+
const reportPreview = claudeResult?.length > 500 ? claudeResult.substring(0, 500) + '...' : claudeResult;
|
|
271
|
+
debugLog(`AI 审核报告内容预览:${reportPreview}`);
|
|
272
|
+
|
|
257
273
|
// 使用正则提取 LINE_INFO 内容(支持换行)
|
|
258
274
|
const lineInfoMatch = claudeResult?.match(/<LINE_INFO>\s*\[([^\]]*)\]\s*<\/LINE_INFO>/);
|
|
259
275
|
const hasLineInfoTag = lineInfoMatch !== null && lineInfoMatch !== undefined;
|
|
@@ -262,33 +278,40 @@ ${diffObject.diff}`;
|
|
|
262
278
|
const lineInfoContent = hasLineInfoTag ? lineInfoMatch[1].replace(/\s/g, '') : '';
|
|
263
279
|
const hasNonEmptyLineInfo = hasLineInfoTag && lineInfoContent !== '';
|
|
264
280
|
|
|
265
|
-
|
|
281
|
+
debugLog(`LINE_INFO 检查结果:hasLineInfoTag=${hasLineInfoTag}, hasNonEmptyLineInfo=${hasNonEmptyLineInfo}, lineInfoContent=[${lineInfoContent}]`);
|
|
282
|
+
|
|
283
|
+
// LINE_INFO 为空或不存在 → 说明无问题,直接返回标准空格式
|
|
266
284
|
if (!hasLineInfoTag || !hasNonEmptyLineInfo) {
|
|
267
|
-
debugLog(
|
|
268
|
-
return { reportContent:
|
|
285
|
+
debugLog(`【决策】LINE_INFO 为空或不存在,说明无问题,直接返回标准空格式`);
|
|
286
|
+
return { reportContent: '<REPORT>\n## 🤖 AI 代码审查结果\n\n</REPORT>', lineInfo: '[]' };
|
|
269
287
|
}
|
|
270
288
|
|
|
271
289
|
// LINE_INFO 有行号 → 继续检查报告内容
|
|
272
290
|
// 先检查是否有严重问题(放宽匹配,只检查"严重问题"关键词)
|
|
273
291
|
const hasSeriousProblem = claudeResult && claudeResult.includes('严重问题');
|
|
274
292
|
|
|
293
|
+
debugLog(`严重问题检查:hasSeriousProblem=${hasSeriousProblem}`);
|
|
294
|
+
|
|
275
295
|
// 无严重问题 → 直接返回标准空格式
|
|
276
296
|
if (!hasSeriousProblem) {
|
|
277
|
-
debugLog(
|
|
297
|
+
debugLog(`【决策】报告无严重问题,返回标准空格式`);
|
|
278
298
|
return { reportContent: claudeResult, lineInfo: lineInfoContent };
|
|
279
299
|
}
|
|
280
300
|
|
|
281
301
|
// 有严重问题 → 检查标题是否符合要求
|
|
282
302
|
const hasValidTitle = claudeResult && claudeResult.includes('🤖 AI 代码审查结果');
|
|
303
|
+
|
|
304
|
+
debugLog(`标题检查:hasValidTitle=${hasValidTitle}`);
|
|
305
|
+
|
|
283
306
|
if (hasValidTitle) {
|
|
284
|
-
debugLog(
|
|
307
|
+
debugLog(`【决策】报告包含严重问题且标题正确,接受结果 (尝试 ${attempts})`);
|
|
285
308
|
return extractReportContent(claudeResult);
|
|
286
309
|
}
|
|
287
310
|
|
|
288
311
|
// 有严重问题但标题不符合 → 重试
|
|
289
|
-
debugLog(
|
|
312
|
+
debugLog(`【决策】报告包含严重问题但标题不符合要求 (尝试 ${attempts}),将重试...`);
|
|
290
313
|
if (attempts >= maxAttempts) {
|
|
291
|
-
debugLog(
|
|
314
|
+
debugLog(`【决策】已达到最大重试次数 ${maxAttempts},返回最后一次结果`);
|
|
292
315
|
return extractReportContent(claudeResult);
|
|
293
316
|
}
|
|
294
317
|
} catch (error) {
|