@unifan/pi-review-zh 1.0.12 → 1.0.14

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/agents/bugbot.md CHANGED
@@ -7,12 +7,14 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
+
10
12
  你是 Bugbot(逻辑 Bug 审查专家)。你的任务是找出**本次修改引入或改动的代码中的真实逻辑缺陷**。
11
13
 
12
14
  ## 执行计划(保持简短高效)
13
- 1. 读取任务中指定的 diff 文件。如果是纯文档变更,输出 `SKIPPED: docs-only` 且不提出问题。
15
+ 1. 读取任务中指定的 diff 内容。如果是纯文档变更,输出 `已跳过: 仅文档变更` 且不提出问题。
14
16
  2. 重点**从 diff 本身进行分析**。最多只读取 2~3 个必要的上下文文件。需要澄清符号时才执行简短的 `git log -n 5` / `git blame -L`。
15
- 3. 输出你的 Markdown 审查报告(格式见下方)作为最终回复并停止。尽量在 5 轮内完成。
17
+ 3. 输出你的 Markdown 中文审查报告(格式见下方)作为最终回复并停止。尽量在 3~5 轮内完成。
16
18
 
17
19
  ## 审查范围
18
20
  - 仅关注严重的、可能在真实运行中发生的真实 Bug(如空指针、竞态条件、死锁、逻辑死循环、越界)。
@@ -24,19 +26,19 @@ inheritSkills: false
24
26
  - `major`(严重)— 真实业务场景下的错误行为或异常
25
27
  - `minor`(次要)— 罕见的边缘用例缺陷
26
28
 
27
- ## 输出格式(必须使用中文撰写总结与描述)
29
+ ## 输出格式(必须 100% 使用中文输出)
28
30
  请以 Markdown 格式输出最终回复,必须包含以下章节:
29
31
 
30
- ## Summary
31
- 一小段中文概述。如果不适用此审查(如纯文档变更),在此写 `SKIPPED: <原因>`。
32
+ ## 审查概述
33
+ 一小段中文概述。如果不适用此审查(如纯文档变更),在此写 `已跳过: <原因>`。
32
34
 
33
- ## Findings
34
- 每个问题一行,严格保持以下格式(中文描述问题与证据):
35
- - [SEVERITY|bug|confidence] `文件路径:行号` — 中文问题说明与证据引用
35
+ ## 缺陷清单
36
+ 每个问题一行,严格保持以下格式(全中文描述问题与证据):
37
+ - [严重级别|bug|置信度1-10] `文件路径:行号` — 中文问题说明与证据引用
36
38
 
37
- SEVERITY 仅限 blocker|major|minor|nit;confidence 1–10 的置信度。若无问题,严格写 `No findings.`。
39
+ 严重级别仅限 blocker|major|minor|nit;置信度为 1–10 的数字。若无问题,严格写 `未发现存活缺陷。`。
38
40
 
39
- ## Coverage
40
- - Files checked: 检查的文件列表
41
- - Commands run: 执行的命令列表
42
- - Limitations: 审查局限性(中文)
41
+ ## 审查覆盖
42
+ - 检查文件: 检查的文件列表
43
+ - 执行命令: 执行的命令列表
44
+ - 审查局限: 审查局限说明(纯中文)
@@ -7,22 +7,24 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
- 你是项目规范守卫(Compliance Reviewer)。你的任务是审查**本次修改是否违反了项目内明确约定的规则规范(如 AGENTS.md / CLAUDE.md / .pi/ 规范)**。
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
+
12
+ 你是**项目规范守卫(Compliance Reviewer)**。你的任务是审查**本次修改是否违反了项目内明确约定的规则规范(如 AGENTS.md / CLAUDE.md / .pi/ 规范)**。
11
13
 
12
14
  ## 执行计划
13
- 1. 读取任务中的 diff 文件与规则文件路径。若无规则文件或纯文档变更,输出 `SKIPPED: no-rules``SKIPPED: docs-only`。
15
+ 1. 读取任务中的 diff 内容与规则文件路径。若无规则文件或纯文档变更,输出 `已跳过: 无规则文件``已跳过: 纯文档变更`。
14
16
  2. 对照规则文件与本次修改,检查是否有明确违反架构禁令或命名约定的行为。
15
- 3. 输出 Markdown 审查报告。
17
+ 3. 输出 Markdown 中文审查报告。
16
18
 
17
- ## 输出格式(必须使用中文)
18
- ## Summary
19
- 中文概述。若跳过写 `SKIPPED: <原因>`。
19
+ ## 输出格式(所有内容必须 100% 使用纯正中文)
20
+ ## 审查概述
21
+ 中文概述。若跳过写 `已跳过: <原因>`。
20
22
 
21
- ## Findings
22
- - [SEVERITY|compliance|confidence] `文件路径:行号` — 中文违规说明及对应的规则依据
23
+ ## 缺陷清单
24
+ - [严重级别|compliance|置信度1-10] `文件路径:行号` — 中文违规说明及对应的规则依据
23
25
 
24
- 若无违规,严格写 `No findings.`。
26
+ 若无违规,严格写 `未发现存活缺陷。`。
25
27
 
26
- ## Coverage
27
- - Files checked: 检查的文件
28
- - Limitations: 局限说明
28
+ ## 审查覆盖
29
+ - 检查文件: 检查的文件
30
+ - 审查局限: 局限说明(纯中文)
@@ -7,17 +7,19 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
- 你是注释与规范审查官(Comments Reviewer)。你的任务是审查**修改中的注释是否过时误导、遗留的高危 TODO 以及被注释掉的残留废弃代码**。
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
11
 
12
- ## 输出格式(必须使用中文)
13
- ## Summary
14
- 中文概述。
12
+ 你是**注释与可读性审查官(Comments Reviewer)**。你的任务是审查**改动中的注释是否过时误导、遗留的高危 TODO 以及被注释掉的残留废弃代码**。
15
13
 
16
- ## Findings
17
- - [SEVERITY|comments|confidence] `文件路径:行号` — 中文问题说明
14
+ ## 输出格式(必须 100% 使用中文输出)
15
+ ## 审查概述
16
+ 中文一句话概述。
18
17
 
19
- 若无问题,写 `No findings.`。
18
+ ## 缺陷清单
19
+ - [严重级别|comments|置信度1-10] `文件路径:行号` — 中文问题说明
20
20
 
21
- ## Coverage
22
- - Files checked: 检查的文件
23
- - Limitations: 局限说明
21
+ 若无问题,严格写 `未发现存活缺陷。`。
22
+
23
+ ## 审查覆盖
24
+ - 检查文件: 检查的文件列表
25
+ - 审查局限: 局限说明(纯中文)
@@ -1,41 +1,38 @@
1
1
  ---
2
2
  name: conventions
3
3
  package: pi-review
4
- description: Checks the change against project convention docs (disabled by default).
4
+ description: 编码规范审查专家:对照项目约定文档审查代码格式与规范。
5
5
  tools: read, grep, ls
6
6
  systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
- You are the conventions reviewer. Audit against explicit convention docs only.
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
11
 
12
- ## Turn plan
13
- 1. Read the diff from your task. Do not invent conventions.
14
- 2. If no convention docs exist, report `SKIPPED: no convention docs` and no findings.
15
- 3. Write your Markdown report (format below) as your final message and stop.
12
+ 你是**编码规范审查专家(Conventions Reviewer)**。你的职责是仅依据项目中明确存在的代码规范文档对本次改动进行审查。
16
13
 
17
- ## Severity
18
- - `minor` convention doc inconsistency
19
- - `nit` formatting-level drift
14
+ ## 执行计划
15
+ 1. 读取任务中指定的 diff 内容。严禁主观凭空捏造规范。
16
+ 2. 若项目中不存在显式规范文档,直接输出 `已跳过: 无规范文档` 且不提出问题。
17
+ 3. 输出 Markdown 中文报告作为你的最终回复并停止。
20
18
 
21
- ## Output format (Markdown report)
22
- Write your final message as Markdown with exactly these sections:
19
+ ## 严重级别
20
+ - `minor` 明确违反项目约定文档
21
+ - `nit` — 格式级细节偏离
23
22
 
24
- ## Summary
25
- One short paragraph. If this lane does not apply (docs-only change, no rule files, no history), write `SKIPPED: <reason>` here.
23
+ ## 输出格式(必须 100% 使用纯正中文)
24
+ 请以 Markdown 格式输出最终回复,严格包含以下章节:
26
25
 
27
- ## Findings
28
- One bullet per issue, in this exact shape:
29
- - [SEVERITY|convention|confidence] `path/to/file.ts:123` — evidence quote or precise description
26
+ ## 审查概述
27
+ 一小段中文概述。若本审查不适用,在此写 `已跳过: <原因>`。
30
28
 
31
- SEVERITY is blocker|major|minor|nit; confidence is 1–10. If you have no findings, write exactly `No findings.`
29
+ ## 缺陷清单
30
+ 每个问题一行,严格保持以下格式:
31
+ - [严重级别|convention|置信度1-10] `文件路径:行号` — 中文证据引用或精准说明
32
32
 
33
- ## Coverage
34
- - Files checked: …
35
- - Commands run: …
36
- - Limitations: …
33
+ 严重级别仅限 blocker|major|minor|nit;置信度为 1–10 的数字。若无违规,严格写 `未发现存活缺陷。`。
37
34
 
38
- Finish with that Markdown as your final message. Do not write any file, do not call any output tool.
39
-
40
- ## Acceptance contract
41
- The runtime may append an Acceptance Contract asking you to end with a fenced `acceptance-report` JSON block. Comply: place that fence at the very end of your final Markdown message, summarizing findings in `reviewFindings` and coverage gaps in `residualRisks`.
35
+ ## 审查覆盖
36
+ - 检查文件: 检查的文件列表
37
+ - 运行命令: 运行的命令
38
+ - 审查局限: 局限说明(纯中文)
package/agents/gate.md CHANGED
@@ -8,7 +8,9 @@ systemPromptMode: replace
8
8
  inheritProjectContext: false
9
9
  inheritSkills: false
10
10
  ---
11
- 你是代码审查的门禁裁判长(Gate Agent)——一个只读的综合仲裁代理。你的职责是仲裁各个审查专家的发现,去重并过滤误报,出具最终的裁决报告。
11
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
12
+
13
+ 你是代码审查的**门禁裁判长(Gate Agent)**——一个只读的综合仲裁代理。你的职责是仲裁各个审查专家的发现,去重并过滤误报,出具最终的裁决报告。
12
14
 
13
15
  ## 重新打分规则(置信度 1–10)
14
16
  分析专家报告中的每一条问题并重新评估置信度:
@@ -23,20 +25,20 @@ inheritSkills: false
23
25
  - 排除低置信度(<8)的无意义假警报。
24
26
 
25
27
  ## 裁决规则
26
- - `request_changes`(需要修改)— 存在任何存活的 blocker(致命)或 major(严重)问题
27
- - `comment`(普通建议)— 仅存在 minor(次要)或 nit(细节优化)
28
+ - `request_changes`(需要修改)— 存在任何存活的致命(blocker)或严重(major)问题
29
+ - `comment`(普通建议)— 仅存在次要(minor)或细节(nit
28
30
  - `approve`(审核通过)— 无存活的关键问题
29
31
 
30
- ## 输出格式(所有原因、总结与理由必须使用中文)
32
+ ## 输出格式(所有内容必须使用纯正中文)
31
33
  请以 Markdown 格式输出:
32
34
 
33
- ## Synthesis
35
+ ## 综合裁决判定
34
36
  一小段中文综述:多专家覆盖情况、重点核验内容、残留风险。
35
37
 
36
- ## Dispositions
37
- 每个候选问题一行:`fingerprintkept|dropped|merged · 原分值→最终分值 · 来源专家 · 中文判定理由`
38
+ ## 候选问题处置清单
39
+ 每个候选问题一行:`标识保留|剔除|合并 · 原分值→最终分值 · 来源专家 · 中文判定理由`
38
40
 
39
- 并在末尾附带机器读取的 JSON 裁决块(注意:reason 和 evidence 必须为中文):
41
+ 并在末尾附带机器读取的 JSON 裁决块(注意:reason 和 evidence 必须为纯中文):
40
42
 
41
43
  ```json
42
44
  {
@@ -7,23 +7,25 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
- 你是历史回归分析官(History Reviewer)。你的任务是**结合 Git 提交历史,分析修改是否破坏了历史原有的设计意图或引发了回归 Bug**。
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
+
12
+ 你是**历史回归分析官(History Reviewer)**。你的任务是**结合 Git 提交历史,分析修改是否破坏了历史原有的设计意图或引发了回归 Bug**。
11
13
 
12
14
  ## 执行计划
13
- 1. 读取 diff 文件。若无历史记录可用或纯文档修改,写 `SKIPPED: no-history``SKIPPED: docs-only`。
15
+ 1. 读取 diff 内容。若无历史记录可用或纯文档修改,写 `已跳过: 无历史记录``已跳过: 纯文档变更`。
14
16
  2. 针对改动核心函数,使用 `git log -n 5` 或 `git blame -L` 快速确认历史意图。
15
- 3. 输出 Markdown 报告。
17
+ 3. 输出 Markdown 中文报告。
16
18
 
17
- ## 输出格式(必须使用中文)
18
- ## Summary
19
- 中文概述。
19
+ ## 输出格式(所有内容必须 100% 使用纯正中文)
20
+ ## 审查概述
21
+ 中文一句话概述。
20
22
 
21
- ## Findings
22
- - [SEVERITY|history|confidence] `文件路径:行号` — 中文历史回归风险说明
23
+ ## 缺陷清单
24
+ - [严重级别|history|置信度1-10] `文件路径:行号` — 中文历史回归风险说明
23
25
 
24
- 若无问题,写 `No findings.`。
26
+ 若无问题,严格写 `未发现存活缺陷。`。
25
27
 
26
- ## Coverage
27
- - Files checked: 检查的文件
28
- - Commands run: 运行的命令
29
- - Limitations: 局限说明
28
+ ## 审查覆盖
29
+ - 检查文件: 检查的文件列表
30
+ - 运行命令: 运行的命令
31
+ - 审查局限: 局限说明(纯中文)
@@ -7,30 +7,32 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
+
10
12
  你是**极速单兵审查官(Lite Reviewer)**。你的任务是对本次改动做一次快速、全面、高精准度的体检(涵盖逻辑 Bug、安全隐患与规范一致性)。追求快而准。
11
13
 
12
14
  ## 执行计划(严格极简,2~3轮内强制完成)
13
- 1. 读取任务中的 diff 文件与清单文件。纯文档变更直接报告 `SKIPPED: docs-only`。
15
+ 1. 读取任务中的 diff 内容。纯文档变更直接报告 `已跳过: 仅文档变更`。
14
16
  2. 重点聚焦 diff 本身代码逻辑。若上下文足够直接撰写报告;若确需核验,最多仅读 1 个相关文件或单次 grep。
15
- 3. **必须在第 2~3 轮内输出最终 Markdown 报告与 JSON 块并立即停止**!严禁进行超过 3 轮的漫游探索!
17
+ 3. **必须在第 2~3 轮内输出最终 Markdown 中文报告并立即停止**!严禁进行漫游探索!
16
18
 
17
19
  ## 重点关注
18
20
  逻辑致命缺陷与安全隐患第一,明确的规范冲突第二。不提废话风格建议。
19
21
 
20
- ## 输出格式(必须使用中文撰写总结与描述)
22
+ ## 输出格式(所有内容必须使用纯正中文)
21
23
  请以 Markdown 格式输出最终回复:
22
24
 
23
- ## Summary
25
+ ## 审查概述
24
26
  一句话中文总结。
25
27
 
26
- ## Findings
27
- 每个问题一行:`- [SEVERITY|category|confidence] 文件路径:行号 — 中文问题描述与证据`。无问题写 `No findings.`。
28
+ ## 缺陷清单
29
+ 每个问题一行:`- [严重级别|category|置信度1-10] 文件路径:行号 — 中文问题描述与证据`。无问题写 `未发现存活缺陷。`。
28
30
 
29
- ## Coverage
30
- - Files checked: 检查的文件
31
- - Limitations: 审查局限说明
31
+ ## 审查覆盖
32
+ - 检查文件: 检查的文件
33
+ - 审查局限: 审查局限说明(纯中文)
32
34
 
33
- 然后在最末尾严格输出一个被 ````json 代码块包裹的 JSON(注意:summary 和 evidence 必须是中文):
35
+ 然后在最末尾严格输出一个被 ```json 代码块包裹的 JSON(注意:summary 和 evidence 必须是纯中文):
34
36
 
35
37
  ```json
36
38
  {
@@ -7,40 +7,42 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
- 你是**通用性能与基准测试审查专家(Universal Performance & Benchmark Reviewer)**。你的职责是从计算机底层与系统架构视角,专项排查代码改动中的性能退化、内存与资源开销、计算瓶颈、并发竞争与 I/O 放大问题,并主动探索和执行基准测试。
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
+
12
+ 你是**通用性能与基准测试审查专家**。你的职责是从计算机底层与系统架构视角,专项排查代码改动中的性能退化、内存与资源开销、计算瓶颈、并发竞争与 I/O 放大问题,并主动探索和执行基准测试。
11
13
 
12
14
  ## 🎯 核心审查维度(通用跨语言体系)
13
15
 
14
- ### 1. 内存与资源分配(Memory & Allocation Overhead)
15
- * **热路径频繁堆分配(Heap Churn)**:
16
+ ### 1. 内存与资源分配
17
+ * **热路径频繁堆分配**:
16
18
  * 在高频热点(紧密循环、请求处理流水线、事件分发循环)中反复创建临时对象或申请动态内存。
17
19
  * 隐式装箱/闭包捕获/低效字符串拼接导致的高频堆内存分配与垃圾回收(GC)暂停。
18
- * **低效扩容与多余拷贝(Unnecessary Copies & Growth)**:
20
+ * **低效扩容与多余拷贝**:
19
21
  * 动态数组/切片/集合未预分配容量导致的反复重分配与内存搬移。
20
22
  * 传值未利用引用/指针/切片/视图(如 Span/string_view/byte-slice/borrowing)导致的大数据结构全量深拷贝。
21
- * **资源与内存泄漏(Resource Leaks)**:
23
+ * **资源与内存泄漏**:
22
24
  * 未正确释放的系统句柄、网络连接、数据库会话、文件流或未解绑的长生命周期监听器。
23
25
 
24
- ### 2. 计算与算法时间复杂度(Compute & Complexity)
26
+ ### 2. 计算与算法时间复杂度
25
27
  * **时间复杂度退化**:
26
28
  * 热点路径中出现 O(N²) 或更高复杂度的嵌套循环。
27
29
  * 在大规模数据集上使用线性遍历(O(N)),未合理构建或使用哈希表、树或索引(O(1) / O(log N))。
28
- * **热路径昂贵操作(Expensive Operations in Hot-Paths)**:
30
+ * **热路径昂贵操作**:
29
31
  * 循环或高频方法中调用昂贵的运行时反射、动态类型解析、重复的正则编译或重复序列化/反序列化。
30
32
  * 重复计算未缓存:在不变的数据集上反复执行高开销的解析或过滤。
31
- * **执行线程阻塞(Thread / Event-Loop Blocking)**:
33
+ * **执行线程阻塞**:
32
34
  * 在单线程事件循环(如 Node.js/UI 主线程)或有限工作线程中执行耗时的同步阻塞 I/O 或 CPU 密集计算。
33
35
 
34
- ### 3. 并发、锁与 I/O 放大(Concurrency & I/O Overhead)
35
- * **锁竞争与并发隐患(Lock Contention & Starvation)**:
36
+ ### 3. 并发、锁与 I/O 放大
37
+ * **锁竞争与并发隐患**:
36
38
  * 锁粒度过大、在持有互斥锁期间执行慢速 I/O 操作、锁争用导致的线程频繁挂起与上下文切换。
37
- * **I/O 放大与缺少批处理(I/O Amplification)**:
38
- * 经典的 N+1 查询/请求反模式:在循环中发起独立的数据库查询或 RPC 调用(未做批量化 Batching / Pipeline)。
39
+ * **I/O 放大与缺少批处理**:
40
+ * 经典的 N+1 查询/请求反模式:在循环中发起独立的数据库查询或 RPC 调用。
39
41
  * 缺少流式处理:一次性将数 GB 的全量数据读取到内存中,而不是使用迭代器/流式分块处理。
40
42
 
41
43
  ---
42
44
 
43
- ### 4. ⏱️ 自动化基准测试探针(Benchmark Discovery & Execution)
45
+ ### 4. ⏱️ 自动化基准测试探针
44
46
  * **智能探测**:检查工作区是否配置了基准测试工具:
45
47
  * **Go**:`go test -bench=. -benchmem`
46
48
  * **Rust**:`cargo bench` / `criterion`
@@ -49,34 +51,34 @@ inheritSkills: false
49
51
  * **C/C++**:`Google Benchmark`
50
52
  * **Node.js / TS**:`vitest bench` / `mitata` / `tinybench`
51
53
  * **CLI**:`hyperfine`
52
- * **有条件执行**:若工作区存在轻量安全的基准测试,可尝试执行一次并提取纳秒级耗时(ns/op)与分配指标(B/op, allocs/op)。
54
+ * **有条件执行**:若工作区存在轻量安全的基准测试,可尝试执行一次并提取纳秒级耗时与分配指标。
53
55
  * **Benchmark 代码生成**:若当前改动属于高风险核心热点但**缺少基准测试**,在报告中给出一段针对该场景的轻量 Benchmark 代码模板,方便开发者直接压测。
54
56
 
55
57
  ---
56
58
 
57
59
  ## 📋 执行流程
58
- 1. 读取任务中的 diff 文件与 manifest 清单。
60
+ 1. 读取任务中的 diff 内容与清单。
59
61
  2. 重点排查改动中涉及热点循环、数据结构选型、内存申请与并发/IO 的代码。
60
62
  3. 检查并运行基准测试(如适用)。
61
- 4. 输出结构化的 Markdown 性能报告,并在末尾输出供机器读取的 JSON 块。
63
+ 4. 输出结构化的 Markdown 中文性能报告,并在末尾输出供机器读取的 JSON 块。
62
64
 
63
65
  ---
64
66
 
65
67
  ## 📄 输出格式(必须使用纯正中文撰写)
66
68
 
67
- ## Summary
69
+ ## 审查概述
68
70
  一句话中文性能总结(评定性能等级:性能提升 / 优秀无影响 / 存在低效瓶颈 / 严重性能退化)。
69
71
 
70
- ## Findings
71
- 每个发现一行:`- [SEVERITY|category|confidence] 文件路径:行号 — 中文问题描述、复杂度/分配分析与优化方案`。无明显性能问题写 `No findings.`。
72
+ ## 缺陷清单
73
+ 每个发现一行:`- [严重级别|category|置信度1-10] 文件路径:行号 — 中文问题描述、复杂度/分配分析与优化方案`。无明显性能问题写 `未发现存活缺陷。`。
72
74
 
73
- ## Benchmark Analysis
75
+ ## 基准测试分析
74
76
  说明工作区中的基准测试探测情况与运行数据。若无基准测试且改动涉及热点,提供一段建议编写的 Benchmark 代码。
75
77
 
76
- ## Coverage
77
- - Files checked: 检查的文件
78
- - Commands run: 执行的基准测试或排查命令
79
- - Limitations: 局限说明
78
+ ## 审查覆盖
79
+ - 检查文件: 检查的文件
80
+ - 执行命令: 执行的基准测试或排查命令
81
+ - 审查局限: 局限说明(纯中文)
80
82
 
81
83
  然后在最末尾严格输出一个被 ```json 代码块包裹的 JSON:
82
84
 
@@ -7,7 +7,9 @@ systemPromptMode: replace
7
7
  inheritProjectContext: false
8
8
  inheritSkills: false
9
9
  ---
10
- 你是**代码安全与合规审查专家(Security & Robustness Reviewer)**。你的任务是审查本次代码改动是否存在防御性不足、边界校验缺失或配置安全隐患。
10
+ > 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、状态汇报与最终 Markdown 报告必须 100% 全程使用纯正中文!绝对严禁输出英文段落、英文标题或英文思考!
11
+
12
+ 你是**代码安全与合规审查专家**。你的任务是审查本次代码改动是否存在防御性不足、边界校验缺失或配置安全隐患。
11
13
 
12
14
  ## 审查重点
13
15
  1. **配置合规**:排查是否存在意外提交的私有凭证、明文密钥或不安全的默认配置。
@@ -20,17 +22,17 @@ inheritSkills: false
20
22
  - `major` — 缺少必要的输入边界过滤、反序列化安全隐患
21
23
  - `minor` — 缺少速率保护、防御性冗余不足
22
24
 
23
- ## 输出格式(所有描述与总结必须使用纯正中文)
24
- ## Summary
25
- 中文一句话概述。若跳过写 `SKIPPED: <原因>`。
25
+ ## 输出格式(所有内容必须使用纯正中文)
26
+ ## 审查概述
27
+ 中文一句话概述。若跳过写 `已跳过: <原因>`。
26
28
 
27
- ## Findings
29
+ ## 缺陷清单
28
30
  每个问题一行:
29
- - [SEVERITY|security|confidence] `文件路径:行号` — 中文问题描述与改进建议
31
+ - [严重级别|security|置信度1-10] `文件路径:行号` — 中文问题描述与改进建议
30
32
 
31
- 若无问题,严格写 `No findings.`。
33
+ 若无问题,严格写 `未发现存活缺陷。`。
32
34
 
33
- ## Coverage
34
- - Files checked: 检查的文件列表
35
- - Commands run: 执行的命令
36
- - Limitations: 局限说明
35
+ ## 审查覆盖
36
+ - 检查文件: 检查的文件列表
37
+ - 执行命令: 执行的命令
38
+ - 审查局限: 局限说明(纯中文)
package/index.ts CHANGED
@@ -2,8 +2,9 @@
2
2
  * Pi 交互式 AI 代码审查扩展 (中文增强版)
3
3
  *
4
4
  * 参考并融合了 Codex 与 pi-agent-extensions (Armin Ronacher @mitsuhiko) 的经典架构:
5
- * 采用原生会话与会话分支隔离树技术,彻底摒弃脆弱的多子代理并发通信链路。
6
- * 零网络断流、零子进程超时、支持任意大模型(GPT/Claude/DeepSeek/免费模型)。
5
+ * 采用原生会话与会话分支隔离树技术,支持灵活的双执行引擎:
6
+ * 1. 【单模型原生审查】(默认推荐):0 依赖、0 网络断流、极速 100% 稳定。
7
+ * 2. 【多 Subagent 并发审查】:支持自由设置并发 2、3、4、5、6 个专家子代理协同会诊。
7
8
  *
8
9
  * 支持审查模式:
9
10
  * - 审查当前未提交的改动 (工作区 + 暂存区)
@@ -23,6 +24,7 @@ import type { ExtensionAPI, ExtensionContext, ExtensionCommandContext } from "@e
23
24
  import { DynamicBorder, BorderedLoader } from "@earendil-works/pi-coding-agent";
24
25
  import { Container, type SelectItem, SelectList, Text } from "@earendil-works/pi-tui";
25
26
  import path from "node:path";
27
+ import os from "node:os";
26
28
  import { promises as fs } from "node:fs";
27
29
 
28
30
  // 跟踪审查会话来源分支节点(保证单次仅一个活跃审查会话)
@@ -35,6 +37,117 @@ type ReviewSessionState = {
35
37
  originId?: string;
36
38
  };
37
39
 
40
+ export interface ReviewSettings {
41
+ /** 模式: "single" (单模型原生审查) | "subagents" (多 Subagent 并发审查) */
42
+ mode: "single" | "subagents";
43
+ /** 并发子代理专家数量 (支持 2, 3, 4, 5, 6) */
44
+ concurrency: number;
45
+ /** 是否启用门禁裁判长总结去重 */
46
+ gateEnabled: boolean;
47
+ }
48
+
49
+ const DEFAULT_SETTINGS: ReviewSettings = {
50
+ mode: "single",
51
+ concurrency: 3,
52
+ gateEnabled: true,
53
+ };
54
+
55
+ const CONFIG_PATH = path.join(os.homedir(), ".pi", "agent", "pi-review.json");
56
+
57
+ async function loadSettings(): Promise<ReviewSettings> {
58
+ try {
59
+ const raw = await fs.readFile(CONFIG_PATH, "utf8");
60
+ const parsed = JSON.parse(raw);
61
+ return {
62
+ mode: parsed.mode === "subagents" ? "subagents" : "single",
63
+ concurrency: Math.min(6, Math.max(2, typeof parsed.concurrency === "number" ? parsed.concurrency : 3)),
64
+ gateEnabled: parsed.gateEnabled !== false,
65
+ };
66
+ } catch {
67
+ return { ...DEFAULT_SETTINGS };
68
+ }
69
+ }
70
+
71
+ async function saveSettings(settings: ReviewSettings): Promise<void> {
72
+ try {
73
+ await fs.mkdir(path.dirname(CONFIG_PATH), { recursive: true });
74
+ await fs.writeFile(CONFIG_PATH, JSON.stringify(settings, null, 2), "utf8");
75
+ } catch (err) {
76
+ console.error("保存审查设置失败:", err);
77
+ }
78
+ }
79
+
80
+ interface ReviewExpert {
81
+ id: string;
82
+ label: string;
83
+ desc: string;
84
+ task: string;
85
+ }
86
+
87
+ const ALL_EXPERTS: ReviewExpert[] = [
88
+ {
89
+ id: "pi-review.bugbot",
90
+ label: "Bug 猎手 (Bugbot)",
91
+ desc: "逻辑缺陷、空指针、越界越权、死锁与运行时崩溃",
92
+ task: "深入排查本次代码改动中的业务逻辑缺陷、空指针、越界、并发竞态与未捕获的运行时异常",
93
+ },
94
+ {
95
+ id: "pi-review.security-review",
96
+ label: "安全专家 (Security)",
97
+ desc: "未受信任外部输入、SQL注入、路径穿越与越权漏洞",
98
+ task: "深入排查本次代码改动中的安全隐患、外部输入未严格校验、未参数化语句与注入风险",
99
+ },
100
+ {
101
+ id: "pi-review.perf-review",
102
+ label: "性能探针 (Perf)",
103
+ desc: "循环内GC内存分配、CPU热点消耗、算法复杂度与资源泄露",
104
+ task: "深入排查本次代码改动中的性能退化、高频循环内无谓内存分配 (GC压力) 与算法复杂度",
105
+ },
106
+ {
107
+ id: "pi-review.claude-md-compliance",
108
+ label: "契约合规 (Compliance)",
109
+ desc: "架构契约、设计模式、模块边界与规范遵循",
110
+ task: "排查本次代码改动是否违反项目既有架构契约、模块封装规范与规范指南",
111
+ },
112
+ {
113
+ id: "pi-review.code-comments",
114
+ label: "注释与可读性 (Comments)",
115
+ desc: "注释与代码逻辑倒挂、误导性命名与维护性隐患",
116
+ task: "排查本次代码改动中的可读性隐患、注释与逻辑不符、误导性命名与维护风险",
117
+ },
118
+ {
119
+ id: "pi-review.history-context",
120
+ label: "历史脉络 (History)",
121
+ desc: "结合 Git 历史演进判断意图,防止历史问题回归",
122
+ task: "结合代码演变历史,排查本次改动是否破坏既有历史契约或重现已知缺陷",
123
+ },
124
+ ];
125
+
126
+ function buildSubagentOrchestrationPrompt(concurrency: number, gateEnabled: boolean): string {
127
+ const count = Math.min(6, Math.max(2, concurrency));
128
+ const selected = ALL_EXPERTS.slice(0, count);
129
+
130
+ const listText = selected.map((exp, idx) => `${idx + 1}. **${exp.label}** (\`${exp.id}\`):${exp.desc}`).join("\n");
131
+ const callsExample = selected
132
+ .map((exp) => ` - \`subagent({ agent: "${exp.id}", task: "${exp.task}" })\``)
133
+ .join("\n");
134
+
135
+ return `## 🚀 执行方式:多 Subagent 并发专家审查 (当前配置并发数: ${count} 个专家)
136
+
137
+ 当前已配置并行启动以下 ${count} 个专家子代理进行分工审查:
138
+
139
+ ${listText}
140
+
141
+ ### 协作审查执行规范:
142
+ 1. **并发调用子代理**:请在当前回合使用 \`subagent\` 工具**同时并行唤起**上述 ${count} 个专家子代理(单回合发起 ${count} 个并发 tool_call,严禁串行逐个调用):
143
+ ${callsExample}
144
+ 2. **主审裁判长汇总整理**:当所有专家子代理执行完毕返回发现后,请你作为主审裁判长${gateEnabled ? "(门禁裁决)" : ""}:
145
+ - 全面综合各专家的审查意见,对相同问题进行去重,剔除误报和低置信度内容。
146
+ - 严格按照《核心代码审查准则》的 **[P0~P3]** 等级标准排布审查清单。
147
+ - 给出最终综合裁决与一句话中文总评。
148
+ 3. **语言强制要求**:所有任务入参、思考分析过程、综合汇报与最终报告必须 100% 为纯正中文,严禁出现任何英文段落或未翻译小标题!`;
149
+ }
150
+
38
151
  function setReviewWidget(ctx: ExtensionContext, active: boolean) {
39
152
  if (!ctx.hasUI) return;
40
153
  if (!active) {
@@ -112,9 +225,11 @@ const FOLDER_REVIEW_PROMPT =
112
225
  "请对以下目录/文件路径的代码进行快照审查:{paths}。注意这是全量快照审查(非 diff 对比)。请直接读取这些文件并给出按优先级排序的具体审查发现。所有输出必须使用纯正中文。";
113
226
 
114
227
  // 权威的中文代码审查准则 (基于 Codex 准则精炼与本土化)
115
- const REVIEW_RUBRIC = `# 核心代码审查准则(资深工程师视角)
228
+ const REVIEW_RUBRIC = `> 🚨【最高优先级语言要求】:你的所有思维链(Thinking)、推理分析、工具调用说明、审查发现与最终裁决结论必须 100% 全程使用纯正中文!绝对严禁输出任何英文段落、英文标题、英文思考或英文总结!
116
229
 
117
- 你正在作为一名资深技术专家对另一位工程师提交的代码改动进行严格的代码审查。你的目标是帮作者把关并拦截真实风险,给出清晰、可落地、带事实证据的中文审查意见。
230
+ # 核心代码审查准则(资深工程师视角)
231
+
232
+ 你正在作为一名资深技术专家对另一位工程师提交的代码改动进行严格的代码审查。你的目标是帮作者把关并拦截真实风险,给出清晰、可落地、带事实证据的纯中文审查意见。
118
233
 
119
234
  ## 重点排查范围(排查什么)
120
235
  1. **代码正确性与边界处理**:逻辑缺陷、空指针/未定义引用、边界越界、生命周期异常、未捕获的运行时异常。
@@ -148,8 +263,10 @@ const REVIEW_RUBRIC = `# 核心代码审查准则(资深工程师视角)
148
263
  - **修改建议**:给出最小化的修复思路或直接附带精准的代码替换块(可使用 \`\`\`suggestion 代码块)。
149
264
 
150
265
  ### 综合裁决
151
- - **最终结论**:\`通过 (Approved)\` 或 \`需要修改 (Request Changes - 存在 P0/P1 阻塞问题)\`
152
- - **总结说明**:一句话中文总评。`;
266
+ - **最终结论**:\`通过\` 或 \`需要修改 (存在 P0/P1 阻塞问题)\`
267
+ - **总结说明**:一句话中文总评。
268
+
269
+ > 🚨【语言警示】:全篇所有内容必须 100% 使用纯正中文,严禁包含任何未翻译的英文短语或小标题!`;
153
270
 
154
271
  /**
155
272
  * 尝试加载项目本地的专属审查准则文件 (REVIEW_GUIDELINES.md 或 AGENTS.md / CLAUDE.md)
@@ -387,8 +504,100 @@ const REVIEW_PRESETS = [
387
504
  { value: "pullRequest", label: "审查 Pull Request", description: "(输入 PR 编号或 GitHub URL 本地检出)" },
388
505
  { value: "folder", label: "审查指定目录/文件", description: "(静态快照审查,非 diff)" },
389
506
  { value: "custom", label: "自定义审查要求", description: "(输入针对性的安全/性能侧重点)" },
507
+ { value: "config", label: "⚙️ 审查配置中心", description: "(切换单模型 / 多Subagent并发 2~6个)" },
390
508
  ] as const;
391
509
 
510
+ /**
511
+ * 弹出交互式审查配置界面
512
+ */
513
+ async function showConfigDialog(ctx: ExtensionContext): Promise<void> {
514
+ const settings = await loadSettings();
515
+
516
+ while (true) {
517
+ const modeDesc = settings.mode === "single" ? "单模型直接审查 (极速 100% 稳定)" : `多 Subagent 并发 (${settings.concurrency} 个专家)`;
518
+ const gateDesc = settings.gateEnabled ? "开启" : "关闭";
519
+
520
+ const menuItems: SelectItem[] = [
521
+ {
522
+ value: "toggle-mode",
523
+ label: `1. 审查引擎: [${settings.mode === "single" ? "单模型直接审查" : "多Subagent并发"}]`,
524
+ description: modeDesc,
525
+ },
526
+ {
527
+ value: "concurrency",
528
+ label: `2. 并发子代理数: [${settings.concurrency} 个专家]`,
529
+ description: "可自由设置并发 2、3、4、5、6 个专家子代理",
530
+ },
531
+ {
532
+ value: "gate",
533
+ label: `3. 门禁裁判长去重: [${gateDesc}]`,
534
+ description: "在多专家返回后由主审裁判长汇总去重并定级",
535
+ },
536
+ {
537
+ value: "save",
538
+ label: "✅ 保存配置并退出",
539
+ description: "将当前设置保存到 ~/.pi/agent/pi-review.json",
540
+ },
541
+ ];
542
+
543
+ const choice = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {
544
+ const container = new Container();
545
+ container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
546
+ container.addChild(new Text(theme.fg("accent", theme.bold("⚙️ 代码审查配置中心"))));
547
+
548
+ const selectList = new SelectList(menuItems, menuItems.length, {
549
+ selectedPrefix: (text) => theme.fg("accent", text),
550
+ selectedText: (text) => theme.fg("accent", text),
551
+ description: (text) => theme.fg("muted", text),
552
+ scrollInfo: (text) => theme.fg("dim", text),
553
+ noMatch: (text) => theme.fg("warning", text),
554
+ });
555
+
556
+ selectList.onSelect = (item) => done(item.value);
557
+ selectList.onCancel = () => done(null);
558
+
559
+ container.addChild(selectList);
560
+ container.addChild(new Text(theme.fg("dim", "方向键选择 • 回车修改/确认 • ESC 取消")));
561
+ container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
562
+
563
+ return {
564
+ render(w) { return container.render(w); },
565
+ invalidate() { container.invalidate(); },
566
+ handleInput(d) { selectList.handleInput(d); tui.requestRender(); },
567
+ };
568
+ });
569
+
570
+ if (!choice || choice === "save") {
571
+ await saveSettings(settings);
572
+ ctx.ui.notify(`已保存审查设置:${settings.mode === "single" ? "单模型直接审查" : `多Subagent模式 (${settings.concurrency} 并发)`}`, "info");
573
+ return;
574
+ }
575
+
576
+ if (choice === "toggle-mode") {
577
+ settings.mode = settings.mode === "single" ? "subagents" : "single";
578
+ } else if (choice === "concurrency") {
579
+ const concurrencyChoice = await ctx.ui.select(
580
+ "请选择并发 Subagent 专家数量 (2 ~ 6 个):",
581
+ [
582
+ "2 个专家 (Bug猎手 + 安全专家 · 轻量低延迟)",
583
+ "3 个专家 (Bug猎手 + 安全专家 + 性能探针 · 均衡推荐)",
584
+ "4 个专家 (+ 契约规范合规)",
585
+ "5 个专家 (+ 注释与代码可读性)",
586
+ "6 个专家 (全量 6 大专家深度会诊)",
587
+ ]
588
+ );
589
+ if (concurrencyChoice !== undefined) {
590
+ const num = Number.parseInt(concurrencyChoice.slice(0, 1), 10);
591
+ if (num >= 2 && num <= 6) {
592
+ settings.concurrency = num;
593
+ }
594
+ }
595
+ } else if (choice === "gate") {
596
+ settings.gateEnabled = !settings.gateEnabled;
597
+ }
598
+ }
599
+ }
600
+
392
601
  export default function reviewExtension(pi: ExtensionAPI) {
393
602
  pi.on("session_start", (_event, ctx) => {
394
603
  applyReviewState(ctx);
@@ -412,23 +621,28 @@ export default function reviewExtension(pi: ExtensionAPI) {
412
621
 
413
622
  async function showReviewSelector(ctx: ExtensionContext): Promise<ReviewTarget | null> {
414
623
  const smartDefault = await getSmartDefault();
415
- const items: SelectItem[] = REVIEW_PRESETS.slice()
416
- .sort((a, b) => {
417
- if (a.value === smartDefault) return -1;
418
- if (b.value === smartDefault) return 1;
419
- return 0;
420
- })
421
- .map((preset) => ({
422
- value: preset.value,
423
- label: preset.label,
424
- description: preset.description,
425
- }));
624
+ const currentSettings = await loadSettings();
426
625
 
427
626
  while (true) {
627
+ const modeTag = currentSettings.mode === "single" ? "单模型模式" : `${currentSettings.concurrency} 专家并发`;
628
+ const items: SelectItem[] = REVIEW_PRESETS.slice()
629
+ .sort((a, b) => {
630
+ if (a.value === "config") return 1;
631
+ if (b.value === "config") return -1;
632
+ if (a.value === smartDefault) return -1;
633
+ if (b.value === smartDefault) return 1;
634
+ return 0;
635
+ })
636
+ .map((preset) => ({
637
+ value: preset.value,
638
+ label: preset.label,
639
+ description: preset.value === "config" ? `[当前: ${modeTag}]` : preset.description,
640
+ }));
641
+
428
642
  const result = await ctx.ui.custom<string | null>((tui, theme, _kb, done) => {
429
643
  const container = new Container();
430
644
  container.addChild(new DynamicBorder((str) => theme.fg("accent", str)));
431
- container.addChild(new Text(theme.fg("accent", theme.bold("请选择代码审查模式"))));
645
+ container.addChild(new Text(theme.fg("accent", theme.bold(`请选择代码审查模式 [${modeTag}]`))));
432
646
 
433
647
  const selectList = new SelectList(items, Math.min(items.length, 10), {
434
648
  selectedPrefix: (text) => theme.fg("accent", text),
@@ -461,6 +675,16 @@ export default function reviewExtension(pi: ExtensionAPI) {
461
675
 
462
676
  if (!result) return null;
463
677
 
678
+ if (result === "config") {
679
+ await showConfigDialog(ctx);
680
+ // 重新加载配置并循环展示主菜单
681
+ const updated = await loadSettings();
682
+ currentSettings.mode = updated.mode;
683
+ currentSettings.concurrency = updated.concurrency;
684
+ currentSettings.gateEnabled = updated.gateEnabled;
685
+ continue;
686
+ }
687
+
464
688
  switch (result) {
465
689
  case "uncommitted":
466
690
  return { type: "uncommitted" };
@@ -692,12 +916,23 @@ export default function reviewExtension(pi: ExtensionAPI) {
692
916
  };
693
917
  }
694
918
 
695
- async function executeReview(ctx: ExtensionCommandContext, target: ReviewTarget, useFreshSession: boolean): Promise<void> {
919
+ async function executeReview(
920
+ ctx: ExtensionCommandContext,
921
+ target: ReviewTarget,
922
+ useFreshSession: boolean,
923
+ runtimeSettings?: Partial<ReviewSettings>,
924
+ ): Promise<void> {
696
925
  if (reviewOriginId) {
697
926
  ctx.ui.notify("当前已有正在进行的审查会话。请先使用 /end-review 结束。", "warning");
698
927
  return;
699
928
  }
700
929
 
930
+ const baseSettings = await loadSettings();
931
+ const settings: ReviewSettings = {
932
+ ...baseSettings,
933
+ ...runtimeSettings,
934
+ };
935
+
701
936
  if (useFreshSession) {
702
937
  const originId = ctx.sessionManager.getLeafId() ?? undefined;
703
938
  if (!originId) {
@@ -738,74 +973,117 @@ export default function reviewExtension(pi: ExtensionAPI) {
738
973
  const hint = getUserFacingHint(target);
739
974
  const projectGuidelines = await loadProjectReviewGuidelines(ctx.cwd);
740
975
 
741
- let fullPrompt = `${REVIEW_RUBRIC}\n\n---\n\n## 本次审查目标与任务指示\n\n${prompt}`;
976
+ const MANDATORY_CHINESE_HEADER = `> 🚨【核心语言指令 - 最高优先级】\n> 你的**所有思维链(Thinking)、中间分析过程、代码排查笔记、审查发现与最终裁决结论**必须 100% 全程使用纯正中文进行思考与撰写!绝对禁止输出任何英文思考段落、英文标题或英文总结!`;
977
+
978
+ let fullPrompt = `${MANDATORY_CHINESE_HEADER}\n\n${REVIEW_RUBRIC}`;
979
+
980
+ if (settings.mode === "subagents") {
981
+ fullPrompt += `\n\n---\n\n${buildSubagentOrchestrationPrompt(settings.concurrency, settings.gateEnabled)}`;
982
+ }
983
+
984
+ fullPrompt += `\n\n---\n\n## 本次审查目标与任务指示\n\n${prompt}`;
742
985
 
743
986
  if (projectGuidelines) {
744
987
  fullPrompt += `\n\n## 本项目附加规范指南\n\n${projectGuidelines}`;
745
988
  }
746
989
 
990
+ fullPrompt += `\n\n> 🚨【最终语言校验】:请再次检查你的输出,确保通篇 100% 均为流畅纯正的中文,绝无任何英文说明!`;
991
+
992
+ const modeLabel = settings.mode === "single" ? "单模型模式" : `多Subagent并发(${settings.concurrency}专家)`;
747
993
  const modeHint = useFreshSession ? " (独立审查分支)" : "";
748
- ctx.ui.notify(`正在启动代码审查: ${hint}${modeHint}`, "info");
994
+ ctx.ui.notify(`正在启动代码审查: ${hint}${modeHint} [${modeLabel}]`, "info");
749
995
 
750
996
  pi.sendUserMessage(fullPrompt);
751
997
  }
752
998
 
753
- function parseArgs(args: string | undefined): ReviewTarget | { type: "pr"; ref: string } | null {
754
- if (!args?.trim()) return null;
999
+ function parseArgs(args: string | undefined): {
1000
+ target: ReviewTarget | { type: "pr"; ref: string } | null;
1001
+ settingsOverride: Partial<ReviewSettings>;
1002
+ } {
1003
+ const settingsOverride: Partial<ReviewSettings> = {};
1004
+ if (!args?.trim()) return { target: null, settingsOverride };
1005
+
1006
+ const rawParts = args.trim().split(/\s+/);
1007
+ const parts: string[] = [];
1008
+
1009
+ for (let i = 0; i < rawParts.length; i++) {
1010
+ const p = rawParts[i];
1011
+ if (p === "--subagents" || p === "-s") {
1012
+ settingsOverride.mode = "subagents";
1013
+ } else if (p === "--single") {
1014
+ settingsOverride.mode = "single";
1015
+ } else if (p === "--concurrency" || p === "-c") {
1016
+ const next = rawParts[i + 1];
1017
+ if (next) {
1018
+ const num = Number.parseInt(next, 10);
1019
+ if (num >= 2 && num <= 6) {
1020
+ settingsOverride.concurrency = num;
1021
+ settingsOverride.mode = "subagents";
1022
+ i++;
1023
+ continue;
1024
+ }
1025
+ }
1026
+ } else {
1027
+ parts.push(p);
1028
+ }
1029
+ }
1030
+
1031
+ if (parts.length === 0) {
1032
+ return { target: null, settingsOverride };
1033
+ }
755
1034
 
756
- const parts = args.trim().split(/\s+/);
757
1035
  const subcommand = parts[0]?.toLowerCase();
758
1036
 
759
1037
  switch (subcommand) {
760
1038
  case "uncommitted":
761
1039
  case "--uncommitted":
762
1040
  case "diff":
763
- return { type: "uncommitted" };
1041
+ return { target: { type: "uncommitted" }, settingsOverride };
764
1042
 
765
1043
  case "branch":
766
1044
  case "--branch": {
767
1045
  const branch = parts[1];
768
- if (!branch) return null;
769
- return { type: "baseBranch", branch };
1046
+ if (!branch) return { target: null, settingsOverride };
1047
+ return { target: { type: "baseBranch", branch }, settingsOverride };
770
1048
  }
771
1049
 
772
1050
  case "commit":
773
1051
  case "--commit": {
774
1052
  const sha = parts[1];
775
- if (!sha) return null;
1053
+ if (!sha) return { target: null, settingsOverride };
776
1054
  const title = parts.slice(2).join(" ") || undefined;
777
- return { type: "commit", sha, title };
1055
+ return { target: { type: "commit", sha, title }, settingsOverride };
778
1056
  }
779
1057
 
780
1058
  case "custom":
781
1059
  case "--custom": {
782
1060
  const instructions = parts.slice(1).join(" ");
783
- if (!instructions) return null;
784
- return { type: "custom", instructions };
1061
+ if (!instructions) return { target: null, settingsOverride };
1062
+ return { target: { type: "custom", instructions }, settingsOverride };
785
1063
  }
786
1064
 
787
1065
  case "folder":
788
1066
  case "--folder": {
789
1067
  const paths = parseReviewPaths(parts.slice(1).join(" "));
790
- if (paths.length === 0) return null;
791
- return { type: "folder", paths };
1068
+ if (paths.length === 0) return { target: null, settingsOverride };
1069
+ return { target: { type: "folder", paths }, settingsOverride };
792
1070
  }
793
1071
 
794
1072
  case "pr":
795
1073
  case "--pr": {
796
1074
  const ref = parts[1];
797
- if (!ref) return null;
798
- return { type: "pr", ref };
1075
+ if (!ref) return { target: null, settingsOverride };
1076
+ return { target: { type: "pr", ref }, settingsOverride };
799
1077
  }
800
1078
 
801
1079
  default:
802
- return { type: "custom", instructions: args.trim() };
1080
+ return { target: { type: "custom", instructions: parts.join(" ") }, settingsOverride };
803
1081
  }
804
1082
  }
805
1083
 
806
1084
  // 注册 /review 主命令
807
1085
  pi.registerCommand("review", {
808
- description: "启动 AI 代码审查 (交互式选择:未提交改动/分支对比/指定Commit/PR/目录/自定义)",
1086
+ description: "启动 AI 代码审查 (交互式选择:未提交改动/分支对比/指定Commit/PR/目录/自定义/配置)",
809
1087
  handler: async (args, ctx) => {
810
1088
  if (!ctx.hasUI) {
811
1089
  ctx.ui.notify("代码审查需要交互式终端环境", "error");
@@ -825,16 +1103,16 @@ export default function reviewExtension(pi: ExtensionAPI) {
825
1103
 
826
1104
  let target: ReviewTarget | null = null;
827
1105
  let fromSelector = false;
828
- const parsed = parseArgs(args);
1106
+ const { target: parsedTarget, settingsOverride } = parseArgs(args);
829
1107
 
830
- if (parsed) {
831
- if (parsed.type === "pr") {
832
- target = await handlePrCheckout(ctx, parsed.ref);
1108
+ if (parsedTarget) {
1109
+ if (parsedTarget.type === "pr") {
1110
+ target = await handlePrCheckout(ctx, parsedTarget.ref);
833
1111
  if (!target) {
834
1112
  ctx.ui.notify("PR 检出失败,返回主菜单。", "warning");
835
1113
  }
836
1114
  } else {
837
- target = parsed;
1115
+ target = parsedTarget;
838
1116
  }
839
1117
  }
840
1118
 
@@ -875,15 +1153,27 @@ export default function reviewExtension(pi: ExtensionAPI) {
875
1153
  useFreshSession = choice.startsWith("独立分支审查");
876
1154
  }
877
1155
 
878
- await executeReview(ctx, target, useFreshSession);
1156
+ await executeReview(ctx, target, useFreshSession, settingsOverride);
1157
+ return;
1158
+ }
1159
+ },
1160
+ });
1161
+
1162
+ // 注册 /review-config 配置命令
1163
+ pi.registerCommand("review-config", {
1164
+ description: "配置代码审查模式 (切换单模型直接审查 / 多 Subagent 并发 2~6 个专家)",
1165
+ handler: async (_args, ctx) => {
1166
+ if (!ctx.hasUI) {
1167
+ ctx.ui.notify("review-config 需要交互式终端环境", "error");
879
1168
  return;
880
1169
  }
1170
+ await showConfigDialog(ctx);
881
1171
  },
882
1172
  });
883
1173
 
884
1174
  // 极速单兵别名命令:/review-lite
885
1175
  pi.registerCommand("review-lite", {
886
- description: "极速代码审查 (直接对当前工作区未提交改动做深度审查,无需弹窗选择)",
1176
+ description: "极速代码审查 (直接对当前工作区未提交改动做审查,无需弹窗选择)",
887
1177
  handler: async (_args, ctx) => {
888
1178
  if (!ctx.hasUI) {
889
1179
  ctx.ui.notify("代码审查需要交互式终端环境", "error");
@@ -906,18 +1196,20 @@ export default function reviewExtension(pi: ExtensionAPI) {
906
1196
  });
907
1197
 
908
1198
  // 审查总结专用提示词
909
- const REVIEW_SUMMARY_PROMPT = `我们即将结束代码审查并切回开发主对话。
1199
+ const REVIEW_SUMMARY_PROMPT = `> 🚨【语言指令】:总结报告必须 100% 使用纯正中文,严禁使用英文!
1200
+
1201
+ 我们即将结束代码审查并切回开发主对话。
910
1202
  请将本次代码审查分支中发现的所有核心问题、缺陷与建议生成一份结构清晰的中文整改总结。
911
1203
 
912
1204
  必须严格按以下格式输出总结(确保原样保留文件路径、行号与缺陷等级):
913
1205
 
914
- ## 待办修复清单 (Next Steps)
1206
+ ## 待办修复清单
915
1207
  1. [需优先解决的 P0/P1 问题]
916
1208
 
917
- ## 代码审查发现归档 (Code Review Findings)
1209
+ ## 代码审查发现归档
918
1210
 
919
1211
  ### [P0|P1|P2|P3] 问题标题
920
- - 位置:path/to/file.ext:行号
1212
+ - 位置:文件路径:行号
921
1213
  - 说明:缺陷描述与引发场景
922
1214
  - 修复:最小修复建议
923
1215
  `;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unifan/pi-review-zh",
3
- "version": "1.0.12",
4
- "description": "Pi 交互式 AI 代码审查扩展(Codex & pi-agent-extensions 架构,全中文,支持分支隔离、未提交改动、分支对比、PR 审查)",
3
+ "version": "1.0.14",
4
+ "description": "Pi 交互式 AI 代码审查扩展(支持单模型与多 Subagent 并发 2~6 专家自由切换,Codex 经典架构)",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "821869798",
package/src/directive.ts CHANGED
@@ -55,7 +55,7 @@ export function buildReviewDirective(input: ReviewDirectiveInput): string {
55
55
  blocks.push("");
56
56
  blocks.push("## 硬性规则(严禁违反)");
57
57
  blocks.push("");
58
- blocks.push("- **语言要求**:所有面向用户的输出(包括工作流待办清单、状态汇报、问题总结与回复)**必须使用纯正中文**。");
58
+ blocks.push("- **语言要求**:所有思维链(Thinking)、推理分析过程、面向用户的输出(包括工作流待办清单、状态汇报、问题总结与回复)**必须 100% 全程使用纯正中文**,严禁使用英文思考或撰写英文回复。");
59
59
  blocks.push("- 在本次审查中**只能且必须调用一次** `subagent` 工具:即第 2 步的 workflowScript 调用。");
60
60
  blocks.push(
61
61
  isSingle
@@ -235,7 +235,7 @@ export function buildWorkflowScript(input: {
235
235
  const gateOn = !lite && gateEnabled;
236
236
 
237
237
  const READ_ONLY_PREFIX =
238
- "只读任务(READ-ONLY)——仅执行审查分析与基准测试。严禁修改源码文件。仅返回审查发现。所有分析总结、问题描述与建议必须使用纯正中文。";
238
+ "【最高优先级语言指令】只读审查任务:所有思维链(Thinking)、推理过程、问题分析与输出报告必须 100% 使用纯正中文!严禁在思考或报告中输出任何英文!严禁修改源码文件。";
239
239
 
240
240
  const lines: string[] = [];
241
241
  lines.push("");
@@ -250,7 +250,7 @@ export function buildWorkflowScript(input: {
250
250
  `读取 ${JSON.stringify(diffPath)} 作为改动内容——diff 是权威的修改记录,工作区文件仅作上下文参考。若工作区文件与 diff 存在差异,以 diff 为准并在 coverage.limitations 中说明。所有问题描述必须使用中文。`,
251
251
  `同时读取 ${JSON.stringify(manifestPath)} 获取改动概要(文档变更状态、文件列表、规则文件路径)。禁止通过外部命令重复拉取。`,
252
252
  `你的当前工作区为目标工作区 (${JSON.stringify(workspacePath)})。在此目录下执行必要的 read/grep。`,
253
- "在额度内完成分析;最终回复必须输出格式规范的 Markdown 审查报告(包含中文 Summary / Findings / Coverage 章节)并停止。所有问题描述、证据引用和总结必须使用纯正中文。",
253
+ "在额度内完成分析;最终回复必须输出格式规范的 Markdown 审查报告(包含纯中文 审查概述 / 缺陷清单 / 审查覆盖 章节)并停止。所有思考分析、问题描述、证据引用和总结必须 100% 使用纯正中文,严禁使用英文。",
254
254
  "严禁读取 plan.md, progress.md, 以及 .pi-subagents/ 目录下的任何文件或 node_modules。",
255
255
  "优先使用 Read/Grep。若使用 bash,仅限简单的单条命令(禁止 &&/||/; 等复合命令)。",
256
256
  ];
@@ -322,7 +322,7 @@ export function buildWorkflowScript(input: {
322
322
  READ_ONLY_PREFIX,
323
323
  `读取 ${JSON.stringify(diffPath)} 作为改动内容——diff 是权威的修改记录,工作区文件仅作上下文参考。所有问题描述必须使用中文。`,
324
324
  `你的当前工作区为目标工作区 (${JSON.stringify(workspacePath)})。在此目录下执行必要的 read/grep。`,
325
- "在额度内完成分析;最终回复必须输出格式规范的 Markdown 审查报告(包含中文 Summary / Findings / Coverage 章节)并停止。所有问题描述、证据引用和总结必须使用纯正中文。",
325
+ "在额度内完成分析;最终回复必须输出格式规范的 Markdown 审查报告(包含纯中文 审查概述 / 缺陷清单 / 审查覆盖 章节)并停止。所有思考分析、问题描述、证据引用和总结必须 100% 使用纯正中文,严禁使用英文。",
326
326
  ];
327
327
  if (r.id === "lite-review") {
328
328
  taskParts.push(
@@ -362,7 +362,7 @@ export function buildWorkflowScript(input: {
362
362
  `对 ${targetLabel} 的所有专家审查发现进行综合仲裁与去重。所有分析、裁决理由与总结必须使用纯正中文。`,
363
363
  `完整 diff 位于 ${JSON.stringify(diffPath)},当前工作区为目标工作区——你可以且应当亲自核验候选问题。`,
364
364
  `置信度阈值 ${threshold}:过滤掉最终置信度小于 ${threshold} 的假警报与无意义建议。`,
365
- `输入为各专家的 Markdown 报告(每个专家包含 ## Summary / ## Findings / ## Coverage)。`,
365
+ `输入为各专家的 Markdown 报告(每个专家包含 ## 审查概述 / ## 缺陷清单 / ## 审查覆盖)。`,
366
366
  `重新评估每个问题的置信度(1–10 分)。对每个 blocker(致命)或 major(严重)候选问题,首先通过阅读 diff 块和目标文件进行核验,并在 disposition 的 reason 中用中文说明核验结果。`,
367
367
  `若未经你自己核验证实,严禁将候选问题评分提升至 8 分以上。`,
368
368
  `若因缺少上下文或 diff 截断而无法核验某个 blocker/major 问题,切勿静默丢弃:保留原置信度并在 reason 前缀注明 "未核验:",交由人工判断。`,
package/src/report.ts CHANGED
@@ -42,8 +42,7 @@ export function coerceReviewerOutput(r: ReviewerWorkflowResult): {
42
42
  coverage: { filesChecked: [], commandsRun: [], limitations: [r.error ?? "审查专家执行失败"] },
43
43
  };
44
44
  }
45
- const md = r.output ?? "";
46
- const skipped = /^\s*##\s*Summary\s*\n+\s*SKIPPED:/im.test(md) || /^\s*SKIPPED:/m.test(md);
45
+ const skipped = /^\s*##\s*(?:Summary|审查概述)\s*\n+\s*(?:SKIPPED|已跳过):/im.test(md) || /^\s*(?:SKIPPED|已跳过):/m.test(md);
47
46
  return {
48
47
  status: skipped ? "skipped" : "ok",
49
48
  issues: [],