@unifan/pi-review-zh 1.0.10 → 1.0.11
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/lite-review.md +4 -4
- package/package.json +1 -1
- package/src/directive.ts +16 -6
- package/src/lean-agents.ts +10 -6
- package/src/report-tool.ts +21 -4
package/agents/lite-review.md
CHANGED
|
@@ -9,10 +9,10 @@ inheritSkills: false
|
|
|
9
9
|
---
|
|
10
10
|
你是**极速单兵审查官(Lite Reviewer)**。你的任务是对本次改动做一次快速、全面、高精准度的体检(涵盖逻辑 Bug、安全隐患与规范一致性)。追求快而准。
|
|
11
11
|
|
|
12
|
-
##
|
|
13
|
-
1. 读取任务中的 diff
|
|
14
|
-
2.
|
|
15
|
-
3.
|
|
12
|
+
## 执行计划(严格极简,2~3轮内强制完成)
|
|
13
|
+
1. 读取任务中的 diff 文件与清单文件。纯文档变更直接报告 `SKIPPED: docs-only`。
|
|
14
|
+
2. 重点聚焦 diff 本身代码逻辑。若上下文足够直接撰写报告;若确需核验,最多仅读 1 个相关文件或单次 grep。
|
|
15
|
+
3. **必须在第 2~3 轮内输出最终 Markdown 报告与 JSON 块并立即停止**!严禁进行超过 3 轮的漫游探索!
|
|
16
16
|
|
|
17
17
|
## 重点关注
|
|
18
18
|
逻辑致命缺陷与安全隐患第一,明确的规范冲突第二。不提废话风格建议。
|
package/package.json
CHANGED
package/src/directive.ts
CHANGED
|
@@ -243,8 +243,8 @@ export function buildWorkflowScript(input: {
|
|
|
243
243
|
lines.push("try {");
|
|
244
244
|
lines.push(" reviewers = await runs.all([");
|
|
245
245
|
for (const r of reviewers) {
|
|
246
|
-
const
|
|
247
|
-
const
|
|
246
|
+
const tbForId = toolBudgetForReviewer(r.id);
|
|
247
|
+
const turnsForId = r.id === "lite-review" ? { maxTurns: 4, graceTurns: 1 } : budgets.turnBudget;
|
|
248
248
|
const taskParts = [
|
|
249
249
|
READ_ONLY_PREFIX,
|
|
250
250
|
`读取 ${JSON.stringify(diffPath)} 作为改动内容——diff 是权威的修改记录,工作区文件仅作上下文参考。若工作区文件与 diff 存在差异,以 diff 为准并在 coverage.limitations 中说明。所有问题描述必须使用中文。`,
|
|
@@ -254,6 +254,11 @@ export function buildWorkflowScript(input: {
|
|
|
254
254
|
"严禁读取 plan.md, progress.md, 以及 .pi-subagents/ 目录下的任何文件或 node_modules。",
|
|
255
255
|
"优先使用 Read/Grep。若使用 bash,仅限简单的单条命令(禁止 &&/||/; 等复合命令)。",
|
|
256
256
|
];
|
|
257
|
+
if (r.id === "lite-review") {
|
|
258
|
+
taskParts.push(
|
|
259
|
+
"极速模式要求:严格在 2~3 轮内完成!读取 diff 后若无需核验直接出报告;若需核验最多只读 1 个文件或单次 grep,下一轮立即输出最终报告并停止!",
|
|
260
|
+
);
|
|
261
|
+
}
|
|
257
262
|
if (r.id === "claude-md-compliance") {
|
|
258
263
|
taskParts.push(
|
|
259
264
|
"若 change-profile.rulePaths 为空,返回跳过状态:SKIPPED: no-rules,不提出虚构的违规。",
|
|
@@ -301,7 +306,7 @@ export function buildWorkflowScript(input: {
|
|
|
301
306
|
}
|
|
302
307
|
lines.push(` toolBudget: { soft: ${tbForId.soft}, hard: ${tbForId.hard} },`);
|
|
303
308
|
lines.push(
|
|
304
|
-
` turnBudget: { maxTurns: ${
|
|
309
|
+
` turnBudget: { maxTurns: ${turnsForId.maxTurns}, graceTurns: ${turnsForId.graceTurns} },${modelClause}`,
|
|
305
310
|
);
|
|
306
311
|
lines.push(" },");
|
|
307
312
|
}
|
|
@@ -311,14 +316,19 @@ export function buildWorkflowScript(input: {
|
|
|
311
316
|
lines.push(" await new Promise((resolve) => setTimeout(resolve, 800));");
|
|
312
317
|
lines.push(" reviewers = await runs.all([");
|
|
313
318
|
for (const r of reviewers) {
|
|
314
|
-
const
|
|
315
|
-
const
|
|
319
|
+
const tbForId = toolBudgetForReviewer(r.id);
|
|
320
|
+
const turnsForId = r.id === "lite-review" ? { maxTurns: 4, graceTurns: 1 } : budgets.turnBudget;
|
|
316
321
|
const taskParts = [
|
|
317
322
|
READ_ONLY_PREFIX,
|
|
318
323
|
`读取 ${JSON.stringify(diffPath)} 作为改动内容——diff 是权威的修改记录,工作区文件仅作上下文参考。所有问题描述必须使用中文。`,
|
|
319
324
|
`你的当前工作区为目标工作区 (${JSON.stringify(workspacePath)})。在此目录下执行必要的 read/grep。`,
|
|
320
325
|
"在额度内完成分析;最终回复必须输出格式规范的 Markdown 审查报告(包含中文 Summary / Findings / Coverage 章节)并停止。所有问题描述、证据引用和总结必须使用纯正中文。",
|
|
321
326
|
];
|
|
327
|
+
if (r.id === "lite-review") {
|
|
328
|
+
taskParts.push(
|
|
329
|
+
"极速模式要求:严格在 2~3 轮内完成!读取 diff 后若无需核验直接出报告;若需核验最多只读 1 个文件或单次 grep,下一轮立即输出最终报告并停止!",
|
|
330
|
+
);
|
|
331
|
+
}
|
|
322
332
|
const modelClause =
|
|
323
333
|
r.model && r.model !== "inherit"
|
|
324
334
|
? `\n model: ${JSON.stringify(r.model)},`
|
|
@@ -337,7 +347,7 @@ export function buildWorkflowScript(input: {
|
|
|
337
347
|
}
|
|
338
348
|
lines.push(` toolBudget: { soft: ${tbForId.soft}, hard: ${tbForId.hard} },`);
|
|
339
349
|
lines.push(
|
|
340
|
-
` turnBudget: { maxTurns: ${
|
|
350
|
+
` turnBudget: { maxTurns: ${turnsForId.maxTurns}, graceTurns: ${turnsForId.graceTurns} },${modelClause}`,
|
|
341
351
|
);
|
|
342
352
|
lines.push(" },");
|
|
343
353
|
}
|
package/src/lean-agents.ts
CHANGED
|
@@ -25,6 +25,8 @@ export interface LeanBudgetSpec {
|
|
|
25
25
|
defaultToolBudget: ToolBudgetSpec;
|
|
26
26
|
/** Stricter per-child tool budget for history-context (injected per runs.all item). */
|
|
27
27
|
historyToolBudget: ToolBudgetSpec;
|
|
28
|
+
/** Ultra-lean tool budget for lite-review. */
|
|
29
|
+
liteToolBudget: ToolBudgetSpec;
|
|
28
30
|
/** Gate child budgets (injected onto the runs.run("gate", ...) item). */
|
|
29
31
|
gateTurnBudget: { maxTurns: number; graceTurns: number };
|
|
30
32
|
gateToolBudget: ToolBudgetSpec;
|
|
@@ -33,15 +35,17 @@ export interface LeanBudgetSpec {
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
export const LEAN_BUDGETS: LeanBudgetSpec = {
|
|
36
|
-
turnBudget: { maxTurns:
|
|
37
|
-
defaultToolBudget: { soft:
|
|
38
|
-
historyToolBudget: { soft:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
turnBudget: { maxTurns: 8, graceTurns: 1 },
|
|
39
|
+
defaultToolBudget: { soft: 6, hard: 10 },
|
|
40
|
+
historyToolBudget: { soft: 4, hard: 6 },
|
|
41
|
+
liteToolBudget: { soft: 3, hard: 5 },
|
|
42
|
+
gateTurnBudget: { maxTurns: 6, graceTurns: 1 },
|
|
43
|
+
gateToolBudget: { soft: 6, hard: 10 },
|
|
44
|
+
timeoutMs: 600_000,
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
export function toolBudgetForReviewer(id: string): ToolBudgetSpec {
|
|
48
|
+
if (id === "lite-review") return LEAN_BUDGETS.liteToolBudget;
|
|
45
49
|
if (id === "history-context") return LEAN_BUDGETS.historyToolBudget;
|
|
46
50
|
return LEAN_BUDGETS.defaultToolBudget;
|
|
47
51
|
}
|
package/src/report-tool.ts
CHANGED
|
@@ -107,15 +107,32 @@ function emptyCoverage(): ReviewerOutput["coverage"] {
|
|
|
107
107
|
|
|
108
108
|
/** Build a deterministic verdict + report from a workflow return value. */
|
|
109
109
|
export function runReportTool(input: ReportToolInput): ReportToolResult {
|
|
110
|
-
|
|
110
|
+
let rawWorkflowReturn = input.workflowReturn;
|
|
111
|
+
if (typeof rawWorkflowReturn === "string") {
|
|
112
|
+
try {
|
|
113
|
+
rawWorkflowReturn = JSON.parse(rawWorkflowReturn);
|
|
114
|
+
} catch {
|
|
115
|
+
return { ok: false, error: "workflowReturn must be an object or valid JSON string" };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!rawWorkflowReturn || typeof rawWorkflowReturn !== "object") {
|
|
111
119
|
return { ok: false, error: "workflowReturn must be an object" };
|
|
112
120
|
}
|
|
113
|
-
const ret =
|
|
121
|
+
const ret = rawWorkflowReturn as {
|
|
114
122
|
reviewers?: unknown;
|
|
115
123
|
gate?: unknown;
|
|
116
124
|
reviewersShaped?: unknown;
|
|
125
|
+
error?: unknown;
|
|
117
126
|
};
|
|
118
|
-
|
|
127
|
+
let reviewersList = Array.isArray(ret.reviewers) ? (ret.reviewers as unknown[]) : [];
|
|
128
|
+
if (reviewersList.length === 0 && ret.error) {
|
|
129
|
+
reviewersList = [{
|
|
130
|
+
key: "execution-error",
|
|
131
|
+
ok: false,
|
|
132
|
+
error: String(ret.error),
|
|
133
|
+
output: undefined,
|
|
134
|
+
}];
|
|
135
|
+
} else if (!Array.isArray(ret.reviewers)) {
|
|
119
136
|
return { ok: false, error: "workflowReturn.reviewers must be an array" };
|
|
120
137
|
}
|
|
121
138
|
|
|
@@ -124,7 +141,7 @@ export function runReportTool(input: ReportToolInput): ReportToolResult {
|
|
|
124
141
|
const threshold = input.threshold ?? 8;
|
|
125
142
|
const policy = input.verdictPolicy ?? "strict";
|
|
126
143
|
|
|
127
|
-
const reviewersRaw =
|
|
144
|
+
const reviewersRaw = reviewersList as Array<{
|
|
128
145
|
key: string;
|
|
129
146
|
ok: boolean;
|
|
130
147
|
error?: string;
|