@zephyrdeng/pi-review 0.4.8 → 0.4.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/README.md +12 -5
- package/README.zh-CN.md +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/meta-footer.d.ts +7 -0
- package/dist/meta-footer.d.ts.map +1 -0
- package/dist/meta-footer.js +46 -0
- package/dist/meta-footer.js.map +1 -0
- package/dist/meta-footer.test.d.ts +2 -0
- package/dist/meta-footer.test.d.ts.map +1 -0
- package/dist/meta-footer.test.js +30 -0
- package/dist/meta-footer.test.js.map +1 -0
- package/dist/review.d.ts +1 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +11 -2
- package/dist/review.js.map +1 -1
- package/extensions/rv-prompts.test.ts +14 -1
- package/extensions/rv-prompts.ts +9 -8
- package/package.json +2 -2
- package/skills/pi-review/SKILL.md +11 -5
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Works as a standalone CLI, a Pi package (extension + skill), or integrated into
|
|
|
18
18
|
|
|
19
19
|
- **Isolated review sessions** — each review runs in a clean child process with no shared state
|
|
20
20
|
- **Multiple review modes** — code review, multi-lens plan review, adversarial challenge review
|
|
21
|
-
- **Structured output** —
|
|
21
|
+
- **Structured output** — human-readable ASCII footer on stdout; `PI_REVIEW_META_JSON` on stderr for automation
|
|
22
22
|
- **Model-agnostic** — use any model available in your Pi installation
|
|
23
23
|
- **Live streaming** — child review output is forwarded as it arrives (use `--no-stream` to buffer)
|
|
24
24
|
- **Progress logging for AI hosts** — `--progress-log <path>` writes a live JSON event log so agent hosts that buffer tool stdout (Claude Code, Codex, ...) can still show real-time progress
|
|
@@ -120,12 +120,18 @@ approve | request_changes | needs_clarification | blocked
|
|
|
120
120
|
## Open Questions
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
The CLI appends a
|
|
123
|
+
The CLI appends a readable ASCII footer on **stdout**:
|
|
124
124
|
|
|
125
125
|
```
|
|
126
|
-
|
|
126
|
+
── pi-review ────────────────────────────
|
|
127
|
+
Verdict ! REQUEST CHANGES
|
|
128
|
+
Mode code
|
|
129
|
+
Duration 42.3s
|
|
130
|
+
──────────────────────────────────────────
|
|
127
131
|
```
|
|
128
132
|
|
|
133
|
+
For scripts, parse **`PI_REVIEW_META_JSON:`** from **stderr** (same fields as before). Set `PI_REVIEW_META_STDOUT=1` to also emit that JSON line on stdout.
|
|
134
|
+
|
|
129
135
|
## Session Management
|
|
130
136
|
|
|
131
137
|
```bash
|
|
@@ -152,7 +158,7 @@ tail -f -n +1 /tmp/pi-review.jsonl | jq -c --unbuffered '
|
|
|
152
158
|
'
|
|
153
159
|
```
|
|
154
160
|
|
|
155
|
-
The JSON event schema is pi CLI's own internal format, not a contract `pi-review` guarantees — it may change between pi versions. `pi-review` parses it defensively (unparseable lines are skipped, missing events degrade to a diagnostic `parseError`) and still prints the same clean Markdown +
|
|
161
|
+
The JSON event schema is pi CLI's own internal format, not a contract `pi-review` guarantees — it may change between pi versions. `pi-review` parses it defensively (unparseable lines are skipped, missing events degrade to a diagnostic `parseError`) and still prints the same clean Markdown + ASCII footer to stdout once the child exits.
|
|
156
162
|
|
|
157
163
|
## CLI Reference
|
|
158
164
|
|
|
@@ -186,6 +192,7 @@ Override defaults via environment variables:
|
|
|
186
192
|
| `PI_REVIEW_PRESETS` | Path to presets JSON file |
|
|
187
193
|
| `PI_REVIEW_SYSTEM_PROMPT` | Path to system prompt file |
|
|
188
194
|
| `PI_REVIEW_SESSION_DIR` | Directory for persisted review sessions |
|
|
195
|
+
| `PI_REVIEW_META_STDOUT` | Set to `1`/`true` to also print `PI_REVIEW_META_JSON` on stdout (default: stderr only) |
|
|
189
196
|
|
|
190
197
|
## Pi Package Usage
|
|
191
198
|
|
|
@@ -196,7 +203,7 @@ After installing as a Pi package, use the `/rv` slash command:
|
|
|
196
203
|
/rv --mode challenge @docs/design.md
|
|
197
204
|
```
|
|
198
205
|
|
|
199
|
-
The `/rv` command injects a task message for the parent agent (
|
|
206
|
+
The `/rv` command injects a task message for the parent agent (Pi host rules: default streaming, no automatic `--no-stream` or `--progress-log` + the `pi-review` CLI to run). The agent follows the **pi-review** skill and runs an isolated child session. Use plain `/rv @path` in Pi — no extra streaming flags needed.
|
|
200
207
|
|
|
201
208
|
```
|
|
202
209
|
/rv models
|
package/README.zh-CN.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
| 源码(CLI、扩展、`review-presets.json`、提示词、代码里的用户可见文案) | **仅英文** |
|
|
16
16
|
| 文档(本页与英文 README) | **中英均可** |
|
|
17
17
|
|
|
18
|
-
实现与对外协议(如 `
|
|
18
|
+
实现与对外协议(如 `PI_REVIEW_META_JSON`、Verdict 枚举)保持英文,便于自动化与跨工具一致。
|
|
19
19
|
|
|
20
20
|
## 前置条件
|
|
21
21
|
|
|
@@ -62,11 +62,11 @@ pi-review models
|
|
|
62
62
|
|
|
63
63
|
跟进审查时,`--continue` 与首次 `/rv` 一样可**选填** `--mode`、`--model`(以及后续 CLI 支持的其它选项由 skill 直接调用 CLI 时传入)。
|
|
64
64
|
|
|
65
|
-
`/rv`
|
|
65
|
+
`/rv` 会向主会话注入**英文任务说明**(Pi 宿主策略:默认流式、**不要**自动加 `--no-stream` / `--progress-log`),由主 Agent 调用 `pi-review` CLI。普通 `/rv @path` 无需额外参数。需要整段缓冲时显式 `/rv --no-stream`;Claude Code 等宿主见英文 README 的 `--progress-log`。
|
|
66
66
|
|
|
67
67
|
## 输出格式
|
|
68
68
|
|
|
69
|
-
审查结果包含 `## Verdict`、`## Summary`、`## Findings` 等章节,并以 `
|
|
69
|
+
审查结果包含 `## Verdict`、`## Summary`、`## Findings` 等章节,并以 **ASCII 页脚**(`── pi-review` 框线 + Verdict/Mode/Duration/Session)结尾;机器可读 JSON 在 **stderr** 一行 `PI_REVIEW_META_JSON:`(需写 stdout 时设 `PI_REVIEW_META_STDOUT=1`)。
|
|
70
70
|
|
|
71
71
|
## 配置
|
|
72
72
|
|
package/dist/index.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export type { Verdict, ParsedArgs, ReviewPreset, VerdictInfo, ReviewMeta, SplitP
|
|
|
9
9
|
export { VERDICTS } from "./types.js";
|
|
10
10
|
export { fail, hasPathSeparator, expandMaybeHome, normalizeTools } from "./utils.js";
|
|
11
11
|
export { parseVerdict } from "./verdict.js";
|
|
12
|
+
export { formatDurationMs, formatReviewMetaAscii, formatReviewMetaJsonLine } from "./meta-footer.js";
|
|
12
13
|
export { installSkill, uninstallSkill } from "./skill.js";
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EACV,OAAO,EACP,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EACV,OAAO,EACP,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,5 +7,6 @@ export { makeRunSessionDir, newestJsonl } from "./session.js";
|
|
|
7
7
|
export { VERDICTS } from "./types.js";
|
|
8
8
|
export { fail, hasPathSeparator, expandMaybeHome, normalizeTools } from "./utils.js";
|
|
9
9
|
export { parseVerdict } from "./verdict.js";
|
|
10
|
+
export { formatDurationMs, formatReviewMetaAscii, formatReviewMetaJsonLine } from "./meta-footer.js";
|
|
10
11
|
export { installSkill, uninstallSkill } from "./skill.js";
|
|
11
12
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAS9D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAS9D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReviewMeta } from "./types.js";
|
|
2
|
+
export declare function formatDurationMs(ms: number): string;
|
|
3
|
+
/** Human-readable ASCII footer for terminals and Pi chat. */
|
|
4
|
+
export declare function formatReviewMetaAscii(meta: ReviewMeta): string;
|
|
5
|
+
/** Machine-readable line for scripts (written to stderr by default). */
|
|
6
|
+
export declare function formatReviewMetaJsonLine(meta: ReviewMeta): string;
|
|
7
|
+
//# sourceMappingURL=meta-footer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-footer.d.ts","sourceRoot":"","sources":["../src/meta-footer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAS7C,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAOnD;AAMD,6DAA6D;AAC7D,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAmB9D;AAED,wEAAwE;AACxE,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAEjE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const VERDICT_DISPLAY = {
|
|
2
|
+
approve: { label: "APPROVE", mark: "✓" },
|
|
3
|
+
request_changes: { label: "REQUEST CHANGES", mark: "!" },
|
|
4
|
+
needs_clarification: { label: "NEEDS CLARIFICATION", mark: "?" },
|
|
5
|
+
blocked: { label: "BLOCKED", mark: "×" },
|
|
6
|
+
};
|
|
7
|
+
export function formatDurationMs(ms) {
|
|
8
|
+
if (ms < 1000)
|
|
9
|
+
return `${ms}ms`;
|
|
10
|
+
const sec = ms / 1000;
|
|
11
|
+
if (sec < 60)
|
|
12
|
+
return `${sec.toFixed(1)}s`;
|
|
13
|
+
const m = Math.floor(sec / 60);
|
|
14
|
+
const s = Math.round(sec % 60);
|
|
15
|
+
return s > 0 ? `${m}m ${s}s` : `${m}m`;
|
|
16
|
+
}
|
|
17
|
+
function padLabel(label, width) {
|
|
18
|
+
return label.length >= width ? label : label + " ".repeat(width - label.length);
|
|
19
|
+
}
|
|
20
|
+
/** Human-readable ASCII footer for terminals and Pi chat. */
|
|
21
|
+
export function formatReviewMetaAscii(meta) {
|
|
22
|
+
const v = VERDICT_DISPLAY[meta.verdict];
|
|
23
|
+
const labelW = 10;
|
|
24
|
+
const lines = [
|
|
25
|
+
"── pi-review " + "─".repeat(28),
|
|
26
|
+
` ${padLabel("Verdict", labelW)} ${v.mark} ${v.label}`,
|
|
27
|
+
` ${padLabel("Mode", labelW)} ${meta.reviewMode}`,
|
|
28
|
+
];
|
|
29
|
+
if (meta.model)
|
|
30
|
+
lines.push(` ${padLabel("Model", labelW)} ${meta.model}`);
|
|
31
|
+
lines.push(` ${padLabel("Duration", labelW)} ${formatDurationMs(meta.durationMs)}`);
|
|
32
|
+
if (meta.sessionHandle) {
|
|
33
|
+
lines.push(` ${padLabel("Session", labelW)} ${meta.sessionHandle}`);
|
|
34
|
+
lines.push(` ${padLabel("", labelW)} (use /rv --continue <path>)`);
|
|
35
|
+
}
|
|
36
|
+
if (meta.parseError) {
|
|
37
|
+
lines.push(` ${padLabel("Note", labelW)} ${meta.parseError}`);
|
|
38
|
+
}
|
|
39
|
+
lines.push("─".repeat(42));
|
|
40
|
+
return lines.join("\n");
|
|
41
|
+
}
|
|
42
|
+
/** Machine-readable line for scripts (written to stderr by default). */
|
|
43
|
+
export function formatReviewMetaJsonLine(meta) {
|
|
44
|
+
return `PI_REVIEW_META_JSON: ${JSON.stringify(meta)}\n`;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=meta-footer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-footer.js","sourceRoot":"","sources":["../src/meta-footer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-footer.test.d.ts","sourceRoot":"","sources":["../src/meta-footer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { formatDurationMs, formatReviewMetaAscii, formatReviewMetaJsonLine } from "./meta-footer.js";
|
|
4
|
+
const sample = {
|
|
5
|
+
reviewMode: "code",
|
|
6
|
+
verdict: "request_changes",
|
|
7
|
+
verdictSource: "parsed",
|
|
8
|
+
durationMs: 383_500,
|
|
9
|
+
model: "zai/glm-5.2",
|
|
10
|
+
sessionHandle: "/tmp/sessions/run-abc/session.jsonl",
|
|
11
|
+
};
|
|
12
|
+
test("formatDurationMs formats sub-minute and minutes", () => {
|
|
13
|
+
assert.equal(formatDurationMs(450), "450ms");
|
|
14
|
+
assert.equal(formatDurationMs(383_500), "6m 24s");
|
|
15
|
+
});
|
|
16
|
+
test("formatReviewMetaAscii includes verdict and session hint", () => {
|
|
17
|
+
const ascii = formatReviewMetaAscii(sample);
|
|
18
|
+
assert.match(ascii, /REQUEST CHANGES/);
|
|
19
|
+
assert.match(ascii, /6m 24s/);
|
|
20
|
+
assert.match(ascii, /session\.jsonl/);
|
|
21
|
+
assert.match(ascii, /--continue/);
|
|
22
|
+
assert.doesNotMatch(ascii, /PI_REVIEW_META_JSON/);
|
|
23
|
+
});
|
|
24
|
+
test("formatReviewMetaJsonLine is one JSON line", () => {
|
|
25
|
+
const line = formatReviewMetaJsonLine(sample);
|
|
26
|
+
assert.ok(line.startsWith("PI_REVIEW_META_JSON: "));
|
|
27
|
+
const json = JSON.parse(line.slice("PI_REVIEW_META_JSON: ".length).trim());
|
|
28
|
+
assert.equal(json.verdict, "request_changes");
|
|
29
|
+
});
|
|
30
|
+
//# sourceMappingURL=meta-footer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"meta-footer.test.js","sourceRoot":"","sources":["../src/meta-footer.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAGrG,MAAM,MAAM,GAAe;IACzB,UAAU,EAAE,MAAM;IAClB,OAAO,EAAE,iBAAiB;IAC1B,aAAa,EAAE,QAAQ;IACvB,UAAU,EAAE,OAAO;IACnB,KAAK,EAAE,aAAa;IACpB,aAAa,EAAE,qCAAqC;CACrD,CAAC;AAEF,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC3D,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;IACnE,MAAM,KAAK,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;IACvC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAClC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACrD,MAAM,IAAI,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC"}
|
package/dist/review.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ParsedArgs } from "./types.js";
|
|
2
2
|
import { type ChildRunResult } from "./child-process.js";
|
|
3
|
-
/** Ensures
|
|
3
|
+
/** Ensures the ASCII meta footer starts on its own line after streamed child stdout. */
|
|
4
4
|
export declare function metaLinePrefix(childStdout: string, streamMode: boolean): string;
|
|
5
5
|
/** True when the final text must be printed after exit instead of having streamed live. */
|
|
6
6
|
export declare function progressLogBuffersOutput(streamMode: boolean, hasProgressLog: boolean): boolean;
|
package/dist/review.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AACzD,OAAO,EAA2C,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAC;AACzD,OAAO,EAA2C,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAmClG,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,CAG/E;AAED,2FAA2F;AAC3F,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,GAAG,OAAO,CAE9F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAKhH;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAM9D;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA6IjE"}
|
package/dist/review.js
CHANGED
|
@@ -10,6 +10,7 @@ import { extractFinalText } from "./json-events.js";
|
|
|
10
10
|
import { makeRunSessionDir, newestJsonl } from "./session.js";
|
|
11
11
|
import { fail, hasPathSeparator, expandMaybeHome, normalizeTools } from "./utils.js";
|
|
12
12
|
import { resolveConfig } from "./config.js";
|
|
13
|
+
import { formatReviewMetaAscii, formatReviewMetaJsonLine } from "./meta-footer.js";
|
|
13
14
|
function readStdin() {
|
|
14
15
|
if (process.stdin.isTTY)
|
|
15
16
|
return "";
|
|
@@ -34,7 +35,7 @@ function childEnv(piBin) {
|
|
|
34
35
|
PATH: [...new Set(pathEntries.join(":").split(":").filter(Boolean))].join(":"),
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
|
-
/** Ensures
|
|
38
|
+
/** Ensures the ASCII meta footer starts on its own line after streamed child stdout. */
|
|
38
39
|
export function metaLinePrefix(childStdout, streamMode) {
|
|
39
40
|
if (!streamMode || !childStdout)
|
|
40
41
|
return "";
|
|
@@ -188,7 +189,15 @@ export async function runReview(parsed) {
|
|
|
188
189
|
const metaPrefix = metaLinePrefix(stdout, !bufferedPrint);
|
|
189
190
|
if (metaPrefix)
|
|
190
191
|
process.stdout.write(metaPrefix);
|
|
191
|
-
process.stdout.write(
|
|
192
|
+
process.stdout.write(`${formatReviewMetaAscii(meta)}\n`);
|
|
193
|
+
const metaJsonDest = process.env.PI_REVIEW_META_STDOUT?.toLowerCase();
|
|
194
|
+
const jsonLine = formatReviewMetaJsonLine(meta);
|
|
195
|
+
if (metaJsonDest === "1" || metaJsonDest === "true" || metaJsonDest === "stdout") {
|
|
196
|
+
process.stdout.write(jsonLine);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
process.stderr.write(jsonLine);
|
|
200
|
+
}
|
|
192
201
|
process.exit(child.status ?? (child.error || child.signal ? 1 : 0));
|
|
193
202
|
}
|
|
194
203
|
//# sourceMappingURL=review.js.map
|
package/dist/review.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.js","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAuB,MAAM,oBAAoB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../src/review.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { describe, it } from "node:test";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
buildPiReviewArgv,
|
|
5
|
+
buildRvOrchestrationPrompt,
|
|
6
|
+
parseRvArgs,
|
|
7
|
+
validateRvParsed,
|
|
8
|
+
} from "./rv-prompts.js";
|
|
4
9
|
|
|
5
10
|
describe("parseRvArgs / validateRvParsed", () => {
|
|
6
11
|
it("parses continue with optional mode and model", () => {
|
|
@@ -37,6 +42,14 @@ describe("parseRvArgs / validateRvParsed", () => {
|
|
|
37
42
|
]);
|
|
38
43
|
});
|
|
39
44
|
|
|
45
|
+
it("orchestration prompt forbids default no-stream and progress-log in Pi", () => {
|
|
46
|
+
const p = parseRvArgs("@src/foo.ts");
|
|
47
|
+
const prompt = buildRvOrchestrationPrompt(p);
|
|
48
|
+
assert.match(prompt, /Do NOT add --no-stream or --progress-log/);
|
|
49
|
+
assert.match(prompt, /ASCII pi-review footer/);
|
|
50
|
+
assert.doesNotMatch(prompt, /PI_REVIEW_META:/);
|
|
51
|
+
});
|
|
52
|
+
|
|
40
53
|
it("buildPiReviewArgv matches for initial and continue", () => {
|
|
41
54
|
const initial = parseRvArgs("--mode plan --model m/a @doc.md");
|
|
42
55
|
assert.deepEqual(buildPiReviewArgv(initial, "@doc.md"), [
|
package/extensions/rv-prompts.ts
CHANGED
|
@@ -113,13 +113,14 @@ export function buildPiReviewArgv(parsed: RvParsed, target: string): string[] {
|
|
|
113
113
|
return parts;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
-
function
|
|
116
|
+
function piHostRules(): string {
|
|
117
117
|
return [
|
|
118
118
|
"Follow the pi-review skill.",
|
|
119
|
-
"
|
|
119
|
+
"Host: Pi interactive session (/rv).",
|
|
120
|
+
"Run pi-review in an isolated child session; return the review conclusion (Markdown sections) plus the ASCII pi-review footer.",
|
|
121
|
+
"CLI defaults: stream child output live. Do NOT add --no-stream or --progress-log unless the user explicitly asked.",
|
|
120
122
|
"Do not edit, patch, commit, or implement findings unless the user asks separately.",
|
|
121
|
-
"
|
|
122
|
-
"pi-review streams child output by default so the user sees live progress; use --no-stream only if buffering is required.",
|
|
123
|
+
"After pi-review exits, show the user the ASCII footer (lines starting with ── pi-review). Do not paste PI_REVIEW_META_JSON to the user; use Session from the footer for /rv --continue.",
|
|
123
124
|
].join(" ");
|
|
124
125
|
}
|
|
125
126
|
|
|
@@ -127,7 +128,7 @@ export function buildRvOrchestrationPrompt(parsed: RvParsed): string {
|
|
|
127
128
|
if (parsed.modelsOnly) {
|
|
128
129
|
return [
|
|
129
130
|
"Run the pi-review model catalog step.",
|
|
130
|
-
|
|
131
|
+
piHostRules(),
|
|
131
132
|
"Execute: pi-review models",
|
|
132
133
|
"Summarize briefly: provider count and 2–3 model IDs that fit code review vs plan/challenge.",
|
|
133
134
|
"Do not start a review until the user supplies a target (@path or text).",
|
|
@@ -140,7 +141,7 @@ export function buildRvOrchestrationPrompt(parsed: RvParsed): string {
|
|
|
140
141
|
if (!target && !parsed.continueHandle) {
|
|
141
142
|
return [
|
|
142
143
|
"/rv needs a review target.",
|
|
143
|
-
"Usage: /rv [--mode code|plan|challenge] [--model provider/model] [--keep-session]
|
|
144
|
+
"Usage: /rv [--mode code|plan|challenge] [--model provider/model] [--keep-session] @files-or-brief",
|
|
144
145
|
"Continue: /rv --continue <handle> [--mode ...] [--model ...] [follow-up text]",
|
|
145
146
|
"Examples: /rv @src/foo.ts | /rv --mode challenge @docs/design.md | /rv models",
|
|
146
147
|
].join("\n\n");
|
|
@@ -178,7 +179,7 @@ export function buildRvOrchestrationPrompt(parsed: RvParsed): string {
|
|
|
178
179
|
|
|
179
180
|
return [
|
|
180
181
|
parsed.continueHandle ? "Continue a prior pi-review session." : "Run pi-review for the target below.",
|
|
181
|
-
|
|
182
|
+
piHostRules(),
|
|
182
183
|
modeBlock[parsed.mode] ??
|
|
183
184
|
`Mode: ${parsed.mode}. Follow the preset named in review-presets.json when present.`,
|
|
184
185
|
modelStep,
|
|
@@ -197,6 +198,6 @@ export const RV_COMPLETIONS: { value: string; hint: string }[] = [
|
|
|
197
198
|
{ value: "--mode challenge", hint: "adversarial plan review" },
|
|
198
199
|
{ value: "--model ", hint: "provider/model from pi-review models" },
|
|
199
200
|
{ value: "--keep-session", hint: "persist session for follow-up" },
|
|
200
|
-
{ value: "--no-stream", hint: "buffer
|
|
201
|
+
{ value: "--no-stream", hint: "rare: buffer until exit (not default in Pi)" },
|
|
201
202
|
{ value: "--continue ", hint: "resume session; same optional flags as initial /rv" },
|
|
202
203
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zephyrdeng/pi-review",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "Isolated AI-powered code and plan reviews from the command line",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "ZephyrDeng <zephyrTang@aliyun.com>",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"build": "tsc",
|
|
68
68
|
"check": "tsc --noEmit",
|
|
69
69
|
"smoke": "node dist/cli.js --help >/dev/null",
|
|
70
|
-
"test": "npx --yes tsx --test src/child-process.test.ts src/review.meta.test.ts src/json-events.test.ts extensions/rv-prompts.test.ts",
|
|
70
|
+
"test": "npx --yes tsx --test src/child-process.test.ts src/review.meta.test.ts src/meta-footer.test.ts src/json-events.test.ts extensions/rv-prompts.test.ts",
|
|
71
71
|
"test:rv": "npx --yes tsx --test extensions/rv-prompts.test.ts",
|
|
72
72
|
"prepublishOnly": "npm run build",
|
|
73
73
|
"pack:dry": "npm pack --dry-run"
|
|
@@ -23,6 +23,11 @@ node ../../bin/pi-review.js --help
|
|
|
23
23
|
|
|
24
24
|
When resolving this fallback, use the actual directory that contains this `SKILL.md`.
|
|
25
25
|
|
|
26
|
+
## Pi host (`/rv`)
|
|
27
|
+
|
|
28
|
+
- In **Pi interactive** sessions, run `pi-review` with **default streaming only** — do **not** add `--no-stream` or `--progress-log` unless the user explicitly asks.
|
|
29
|
+
- The `/rv` extension injects these rules into the parent agent; ordinary `/rv @path` needs no extra flags.
|
|
30
|
+
|
|
26
31
|
## Streaming vs agent hosts
|
|
27
32
|
|
|
28
33
|
- `pi-review` **streams** child `pi` stdout/stderr to the process terminal by default (`--no-stream` buffers until exit).
|
|
@@ -45,9 +50,9 @@ There is **no** `/status` slash in this skill. When the user asks for **review s
|
|
|
45
50
|
```bash
|
|
46
51
|
ls -lt "${PI_REVIEW_SESSION_DIR:-$HOME/.pi/pi-review/sessions}" 2>/dev/null | head -15 || true
|
|
47
52
|
```
|
|
48
|
-
Mention newest folders and that `sessionHandle`
|
|
53
|
+
Mention newest folders and that **Session** from the ASCII footer (or `sessionHandle` in `PI_REVIEW_META_JSON` on stderr) is used with `--continue`.
|
|
49
54
|
|
|
50
|
-
3. **Last conclusion** — if this conversation already has
|
|
55
|
+
3. **Last conclusion** — if this conversation already has the ASCII `── pi-review` footer, quote verdict, duration, and session path instead of re-running review.
|
|
51
56
|
|
|
52
57
|
4. **Live output** — remind that chat tools may not stream; prefer re-running with `--progress-log <path>` + a background/tail workflow for live progress, or use a **terminal** running `pi-review` (default streaming) as a fallback.
|
|
53
58
|
|
|
@@ -79,7 +84,7 @@ Do not implement findings from a status check; status is informational only.
|
|
|
79
84
|
- Use the model decision from step 1; do not invent model IDs.
|
|
80
85
|
- Omit `--mode` for normal code review; the command defaults to `code`.
|
|
81
86
|
- Use `--keep-session` only when the user wants follow-up questions on this review.
|
|
82
|
-
- Use `--continue <handle>` only with a
|
|
87
|
+
- Use `--continue <handle>` only with a **Session** path from a prior ASCII footer or `sessionHandle` in `PI_REVIEW_META_JSON`.
|
|
83
88
|
- Put file references as `@path` after `--`.
|
|
84
89
|
- Do not ask `pi-review` to edit, patch, commit, or implement.
|
|
85
90
|
- Default streams child output live; add `--no-stream` only when the caller must buffer until exit (cannot combine with `--progress-log`).
|
|
@@ -87,9 +92,10 @@ Do not implement findings from a status check; status is informational only.
|
|
|
87
92
|
Completion criterion: the command includes the resolved model/default choice and a concrete review target.
|
|
88
93
|
|
|
89
94
|
4. Return the result:
|
|
90
|
-
-
|
|
95
|
+
- Show the Markdown review body and the **ASCII footer** (`── pi-review` block on stdout). Do not paste raw `PI_REVIEW_META_JSON` to the user unless they ask for machine output.
|
|
96
|
+
- Scripts: parse `PI_REVIEW_META_JSON:` from **stderr** (or set `PI_REVIEW_META_STDOUT=1` to also emit JSON on stdout).
|
|
91
97
|
- Do not apply findings automatically; implementation is a separate user decision.
|
|
92
|
-
Completion criterion: the user sees the
|
|
98
|
+
Completion criterion: the user sees the review conclusion and readable footer.
|
|
93
99
|
|
|
94
100
|
## Examples
|
|
95
101
|
|