@unifan/pi-review-zh 1.0.14 → 1.0.16
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/index.ts +91 -49
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -200,73 +200,74 @@ type ReviewTarget =
|
|
|
200
200
|
| { type: "folder"; paths: string[] };
|
|
201
201
|
|
|
202
202
|
// 针对不同审查目标的中文提示词
|
|
203
|
+
const LITE_REVIEW_PROMPT =
|
|
204
|
+
"【极速体检模式】请直接运行 `git diff` 快速排查当前未提交改动中的高危逻辑缺陷与安全漏洞。只抓严重级别最高的问题,快速输出审查结论。严禁输出任何步骤清单。所有输出必须使用纯正中文。";
|
|
205
|
+
|
|
206
|
+
const FULL_REVIEW_PROMPT =
|
|
207
|
+
"【全量深度审查模式】请对当前代码改动展开全方位的深度审查。直接运行 `git diff` 全量审阅代码改动,深入排查潜在的业务逻辑隐患、边界异常、并发安全、性能GC开销与架构合规性,直接给出按优先级排序的详尽审查清单。严禁输出任何步骤清单。所有输出必须使用纯正中文。";
|
|
208
|
+
|
|
203
209
|
const UNCOMMITTED_PROMPT =
|
|
204
|
-
"
|
|
210
|
+
"请审查当前代码的所有改动(包含暂存区、未暂存区以及新增文件)。直接运行 `git diff` 与 `git status` 查看代码差异,并直接输出审查发现。严禁输出任何步骤清单或待办列表。所有输出必须使用纯正中文。";
|
|
205
211
|
|
|
206
212
|
const BASE_BRANCH_PROMPT_WITH_MERGE_BASE =
|
|
207
|
-
"请审查当前分支相对于基准分支 '{baseBranch}'
|
|
213
|
+
"请审查当前分支相对于基准分支 '{baseBranch}' 的改动(合并基准 commit: {mergeBaseSha})。直接运行 `git diff {mergeBaseSha}` 查看改动并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。";
|
|
208
214
|
|
|
209
215
|
const BASE_BRANCH_PROMPT_FALLBACK =
|
|
210
|
-
"请审查当前分支相对于基准分支 '{branch}'
|
|
216
|
+
"请审查当前分支相对于基准分支 '{branch}' 的改动。直接使用 `git merge-base` 与 `git diff` 查看改动并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。";
|
|
211
217
|
|
|
212
218
|
const COMMIT_PROMPT_WITH_TITLE =
|
|
213
|
-
'请审查提交 commit {sha} ("{title}") 引入的代码改动。直接运行 `git show {sha}`
|
|
219
|
+
'请审查提交 commit {sha} ("{title}") 引入的代码改动。直接运行 `git show {sha}` 查看差异并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。';
|
|
214
220
|
|
|
215
221
|
const COMMIT_PROMPT =
|
|
216
|
-
"请审查提交 commit {sha} 引入的代码改动。直接运行 `git show {sha}`
|
|
222
|
+
"请审查提交 commit {sha} 引入的代码改动。直接运行 `git show {sha}` 查看差异并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。";
|
|
217
223
|
|
|
218
224
|
const PULL_REQUEST_PROMPT =
|
|
219
|
-
'请审查 Pull Request #{prNumber} ("{title}") 相对于基准分支 \'{baseBranch}\'
|
|
225
|
+
'请审查 Pull Request #{prNumber} ("{title}") 相对于基准分支 \'{baseBranch}\' 的改动(合并基准 commit: {mergeBaseSha})。直接运行 `git diff {mergeBaseSha}` 查看改动并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。';
|
|
220
226
|
|
|
221
227
|
const PULL_REQUEST_PROMPT_FALLBACK =
|
|
222
|
-
'请审查 Pull Request #{prNumber} ("{title}") 相对于基准分支 \'{baseBranch}\'
|
|
228
|
+
'请审查 Pull Request #{prNumber} ("{title}") 相对于基准分支 \'{baseBranch}\' 的改动。直接运行 `git diff` 查看改动并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。';
|
|
223
229
|
|
|
224
230
|
const FOLDER_REVIEW_PROMPT =
|
|
225
|
-
"请对以下目录/文件路径的代码进行快照审查:{paths}
|
|
231
|
+
"请对以下目录/文件路径的代码进行快照审查:{paths}。直接读取这些文件并直接输出审查发现。严禁输出任何步骤清单。所有输出必须使用纯正中文。";
|
|
226
232
|
|
|
227
233
|
// 权威的中文代码审查准则 (基于 Codex 准则精炼与本土化)
|
|
228
|
-
const REVIEW_RUBRIC = `>
|
|
234
|
+
const REVIEW_RUBRIC = `> 🚨【最高执行原则】:
|
|
235
|
+
> 1. **全流程纯中文**:思维链(Thinking)、推理分析与最终报告必须 100% 使用纯正中文,严禁包含任何英文段落或英文小标题!
|
|
236
|
+
> 2. **直接审查,拒绝繁琐步骤**:严禁打印任何工作流待办清单(Checklist)或环境测试命令!直接阅读代码改动并立即输出审查报告!
|
|
229
237
|
|
|
230
|
-
#
|
|
238
|
+
# 核心代码审查准则
|
|
231
239
|
|
|
232
|
-
|
|
240
|
+
你是一名资深技术专家,正在审查提交的代码改动。请直击本质,拦截真实缺陷:
|
|
233
241
|
|
|
234
|
-
##
|
|
235
|
-
1.
|
|
236
|
-
2.
|
|
237
|
-
3.
|
|
238
|
-
4.
|
|
239
|
-
|
|
240
|
-
- 报错与异常必须检查稳定的错误码或类型,严禁用脆弱的错误文本字符串做业务分支判断。
|
|
241
|
-
5. **本次改动引入的缺陷**:只审查本次改动实际引入的问题,严禁把改动前既有的历史代码或未改动代码归咎为缺陷。
|
|
242
|
+
## 重点排查范围
|
|
243
|
+
1. **代码正确性与边界**:业务逻辑漏洞、空指针/未定义引用、边界越界、生命周期异常、未捕获的运行时崩溃。
|
|
244
|
+
2. **并发与状态安全**:竞态条件、死锁隐患、异步缺少等待、脏状态残留。
|
|
245
|
+
3. **性能与内存开销**:高频主循环内的大量堆内存分配 (GC 压力)、不必要的深拷贝、高复杂度算法、资源句柄泄露。
|
|
246
|
+
4. **防御与输入校验**:外部未受信任输入未做严格参数化或校验(SQL注入、路径穿越、越权等)。
|
|
247
|
+
5. **只关注本次改动**:严禁将改动前既有的历史代码当作本次改动的缺陷。
|
|
242
248
|
|
|
243
|
-
##
|
|
244
|
-
- ❌
|
|
245
|
-
- ❌ 严禁提出 Linter
|
|
246
|
-
- ❌
|
|
249
|
+
## 严格过滤误报
|
|
250
|
+
- ❌ 严禁提出吹毛求疵、纯属个人审美的风格建议。
|
|
251
|
+
- ❌ 严禁提出 Linter / 类型检查器会自动捕获的浅层格式建议。
|
|
252
|
+
- ❌ 严禁基于纯主观假设进行无端猜测,每条问题必须有明确代码事实证据。
|
|
247
253
|
|
|
248
|
-
##
|
|
249
|
-
|
|
250
|
-
- **[
|
|
251
|
-
- **[
|
|
252
|
-
- **[
|
|
253
|
-
- **[P3 - 细节优化]** 极轻微的细节优化建议,不影响业务。
|
|
254
|
-
|
|
255
|
-
## 输出格式(所有内容必须使用纯正中文)
|
|
256
|
-
请按以下规范输出审查报告:
|
|
254
|
+
## 缺陷等级标记 [P0~P3]
|
|
255
|
+
- **[P0 - 致命阻塞]** 崩溃、死锁、数据损坏、关键功能不可用,必须阻断合并
|
|
256
|
+
- **[P1 - 紧急待修]** 明确逻辑缺陷、边界异常、严重性能退化,合并前需修复
|
|
257
|
+
- **[P2 - 普通建议]** 局部的健壮性隐患、轻度设计问题
|
|
258
|
+
- **[P3 - 细节优化]** 细节优化与可读性
|
|
257
259
|
|
|
260
|
+
## 输出格式规范(直接输出,无多余寒暄与准备动作)
|
|
258
261
|
### 审查发现清单
|
|
259
|
-
|
|
262
|
+
每个问题按以下格式列出(若无存活缺陷,明确输出:\`未发现存活的代码缺陷,代码质量良好,建议合并。\`):
|
|
260
263
|
- **[P0|P1|P2|P3] 简短标题**:\`文件路径:行号\`
|
|
261
|
-
-
|
|
262
|
-
- **代码证据**:引用 1~3
|
|
263
|
-
-
|
|
264
|
+
- **缺陷说明**:简明说明后果与触发场景。
|
|
265
|
+
- **代码证据**:引用 1~3 行关键代码。
|
|
266
|
+
- **修改建议**:给出最小化修复思路或代码替换块(可使用 \`\`\`suggestion)。
|
|
264
267
|
|
|
265
268
|
### 综合裁决
|
|
266
269
|
- **最终结论**:\`通过\` 或 \`需要修改 (存在 P0/P1 阻塞问题)\`
|
|
267
|
-
-
|
|
268
|
-
|
|
269
|
-
> 🚨【语言警示】:全篇所有内容必须 100% 使用纯正中文,严禁包含任何未翻译的英文短语或小标题!`;
|
|
270
|
+
- **总结说明**:一句话中文总评。`;
|
|
270
271
|
|
|
271
272
|
/**
|
|
272
273
|
* 尝试加载项目本地的专属审查准则文件 (REVIEW_GUIDELINES.md 或 AGENTS.md / CLAUDE.md)
|
|
@@ -430,9 +431,15 @@ async function getDefaultBranch(pi: ExtensionAPI): Promise<string> {
|
|
|
430
431
|
return "main";
|
|
431
432
|
}
|
|
432
433
|
|
|
433
|
-
async function buildReviewPrompt(
|
|
434
|
+
async function buildReviewPrompt(
|
|
435
|
+
pi: ExtensionAPI,
|
|
436
|
+
target: ReviewTarget,
|
|
437
|
+
reviewStyle: "lite" | "full" | "standard" = "standard",
|
|
438
|
+
): Promise<string> {
|
|
434
439
|
switch (target.type) {
|
|
435
440
|
case "uncommitted":
|
|
441
|
+
if (reviewStyle === "lite") return LITE_REVIEW_PROMPT;
|
|
442
|
+
if (reviewStyle === "full") return FULL_REVIEW_PROMPT;
|
|
436
443
|
return UNCOMMITTED_PROMPT;
|
|
437
444
|
|
|
438
445
|
case "baseBranch": {
|
|
@@ -921,6 +928,7 @@ export default function reviewExtension(pi: ExtensionAPI) {
|
|
|
921
928
|
target: ReviewTarget,
|
|
922
929
|
useFreshSession: boolean,
|
|
923
930
|
runtimeSettings?: Partial<ReviewSettings>,
|
|
931
|
+
reviewStyle: "lite" | "full" | "standard" = "standard",
|
|
924
932
|
): Promise<void> {
|
|
925
933
|
if (reviewOriginId) {
|
|
926
934
|
ctx.ui.notify("当前已有正在进行的审查会话。请先使用 /end-review 结束。", "warning");
|
|
@@ -969,29 +977,26 @@ export default function reviewExtension(pi: ExtensionAPI) {
|
|
|
969
977
|
pi.appendEntry(REVIEW_STATE_TYPE, { active: true, originId: lockedOriginId });
|
|
970
978
|
}
|
|
971
979
|
|
|
972
|
-
const prompt = await buildReviewPrompt(pi, target);
|
|
980
|
+
const prompt = await buildReviewPrompt(pi, target, reviewStyle);
|
|
973
981
|
const hint = getUserFacingHint(target);
|
|
974
982
|
const projectGuidelines = await loadProjectReviewGuidelines(ctx.cwd);
|
|
975
983
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
let fullPrompt = `${MANDATORY_CHINESE_HEADER}\n\n${REVIEW_RUBRIC}`;
|
|
984
|
+
let fullPrompt = REVIEW_RUBRIC;
|
|
979
985
|
|
|
980
986
|
if (settings.mode === "subagents") {
|
|
981
987
|
fullPrompt += `\n\n---\n\n${buildSubagentOrchestrationPrompt(settings.concurrency, settings.gateEnabled)}`;
|
|
982
988
|
}
|
|
983
989
|
|
|
984
|
-
fullPrompt += `\n\n---\n\n##
|
|
990
|
+
fullPrompt += `\n\n---\n\n## 本次审查任务指示\n\n${prompt}`;
|
|
985
991
|
|
|
986
992
|
if (projectGuidelines) {
|
|
987
993
|
fullPrompt += `\n\n## 本项目附加规范指南\n\n${projectGuidelines}`;
|
|
988
994
|
}
|
|
989
995
|
|
|
990
|
-
|
|
991
|
-
|
|
996
|
+
const styleTag = reviewStyle === "lite" ? "[极速]" : reviewStyle === "full" ? "[全量]" : "";
|
|
992
997
|
const modeLabel = settings.mode === "single" ? "单模型模式" : `多Subagent并发(${settings.concurrency}专家)`;
|
|
993
998
|
const modeHint = useFreshSession ? " (独立审查分支)" : "";
|
|
994
|
-
ctx.ui.notify(
|
|
999
|
+
ctx.ui.notify(`正在启动代码审查 ${styleTag}: ${hint}${modeHint} [${modeLabel}]`, "info");
|
|
995
1000
|
|
|
996
1001
|
pi.sendUserMessage(fullPrompt);
|
|
997
1002
|
}
|
|
@@ -1191,7 +1196,44 @@ export default function reviewExtension(pi: ExtensionAPI) {
|
|
|
1191
1196
|
return;
|
|
1192
1197
|
}
|
|
1193
1198
|
|
|
1194
|
-
await executeReview(ctx, { type: "uncommitted" }, false);
|
|
1199
|
+
await executeReview(ctx, { type: "uncommitted" }, false, undefined, "lite");
|
|
1200
|
+
},
|
|
1201
|
+
});
|
|
1202
|
+
|
|
1203
|
+
// 全量深度审查命令:/review-full
|
|
1204
|
+
pi.registerCommand("review-full", {
|
|
1205
|
+
description: "全量深度代码审查 (直接对工作区与分支全部改动展开深度审查,无多余前置步骤与待办清单)",
|
|
1206
|
+
handler: async (args, ctx) => {
|
|
1207
|
+
if (!ctx.hasUI) {
|
|
1208
|
+
ctx.ui.notify("代码审查需要交互式终端环境", "error");
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
if (reviewOriginId) {
|
|
1213
|
+
ctx.ui.notify("当前已有正在进行的审查。请先输入 /end-review 完成审查并返回。", "warning");
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
const { code } = await pi.exec("git", ["rev-parse", "--git-dir"]);
|
|
1218
|
+
if (code !== 0) {
|
|
1219
|
+
ctx.ui.notify("当前目录不是有效的 Git 仓库", "error");
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
const { target, settingsOverride } = parseArgs(args);
|
|
1224
|
+
let finalTarget = target && target.type !== "pr" ? target : null;
|
|
1225
|
+
|
|
1226
|
+
if (!finalTarget) {
|
|
1227
|
+
const defaultType = await getSmartDefault();
|
|
1228
|
+
if (defaultType === "baseBranch") {
|
|
1229
|
+
const defaultBranch = await getDefaultBranch(pi);
|
|
1230
|
+
finalTarget = { type: "baseBranch", branch: defaultBranch };
|
|
1231
|
+
} else {
|
|
1232
|
+
finalTarget = { type: "uncommitted" };
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
await executeReview(ctx, finalTarget, false, settingsOverride, "full");
|
|
1195
1237
|
},
|
|
1196
1238
|
});
|
|
1197
1239
|
|