pi-pr-review 1.1.2

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 ADDED
@@ -0,0 +1,192 @@
1
+ # pi-pr-review
2
+
3
+ A model-agnostic GitHub pull-request review prompt for [pi](https://pi.dev).
4
+
5
+ Pass a PR number and pi will:
6
+
7
+ 1. Resolve the PR in the **current directory's git repo** via `gh`.
8
+ 2. Derive the **base branch** and **head (merging) branch** automatically from the PR.
9
+ 3. Review the base↔head diff with disciplined passes (overview, convention compliance, bugs, security/perf, readability), best-effort build/test verification, then validate each candidate.
10
+ 4. Return a **full structured review**: overview, strengths, verification, findings at **every** severity (`nit → P3 → P2 → P1 → P0`) with a blocking flag, correctness/security/performance notes, and a verdict.
11
+ 5. Optionally post the review + inline PR comments (`--comment`).
12
+
13
+ **Captures everything, then ranks it.** Unlike a high-signal-only reviewer, it does not discard minor issues — nits, style, naming, missing edge cases, and "worth confirming" observations are all reported as low-severity findings. The **verdict** depends only on *blocking* (P0/P1) findings, so a clean PR is still approved while its nits are still recorded.
14
+
15
+ No model name is hardcoded anywhere. The package ships an extension that adds **tiered review subagents** — `light` / `medium` / `heavy` — that you map to whatever models you like. Independent review passes fan out through a batch tool so overview, conventions/maintainability, correctness, and security/performance can run in parallel. If the extension isn't loaded, the same prompt runs every pass inline on your current session model, so it always works.
16
+
17
+ ## Requirements
18
+
19
+ - [`gh`](https://cli.github.com/) installed and authenticated (`gh auth login`).
20
+ - Run pi from inside the git repository that hosts the PR (so `gh` auto-detects the repo).
21
+
22
+ ## Install
23
+
24
+ Install straight from the public repo (user scope):
25
+
26
+ ```bash
27
+ pi install git:github.com/10ego/pi-pr-review
28
+ ```
29
+
30
+ Or project scope (shareable with your team, auto-installed on trust):
31
+
32
+ ```bash
33
+ pi install -l git:github.com/10ego/pi-pr-review
34
+ ```
35
+
36
+ You can also install from a local checkout by pointing at the package directory, e.g. `pi install ./pi-pr-review` (add `-l` for project scope).
37
+
38
+ ### Alternative: use the template without packaging
39
+
40
+ The prompt is a plain template — just copy it into a prompts directory pi already scans:
41
+
42
+ ```bash
43
+ # global (all projects)
44
+ cp prompts/pr-review.md ~/.pi/agent/prompts/
45
+ # or per-project
46
+ mkdir -p .pi/prompts && cp prompts/pr-review.md .pi/prompts/
47
+ ```
48
+
49
+ ## Configure the review models
50
+
51
+ Model selection is configuration, not code. There are two layers:
52
+
53
+ ### 1. Tiered subagent models (recommended)
54
+
55
+ The `/pr-review-config` command maps three labels to models:
56
+
57
+ | Tier | Used for | Pick a model that is… |
58
+ |------|----------|----------------------|
59
+ | `light` | overview / strengths / high-level risk scan | fast + cheap |
60
+ | `medium` | convention compliance + readability / maintainability | balanced |
61
+ | `heavy` | bug + security/logic review | strongest |
62
+
63
+ ```
64
+ /pr-review-config # open the settings menu (like /settings & /nervous:config)
65
+ /pr-review-config show # print the current mapping
66
+ /pr-review-config light=<spec> medium=<spec> heavy=<spec> # set non-interactively
67
+ /pr-review-config medium=unset # clear a tier (back to pi default)
68
+ /pr-review-config tools=read,bash,grep,find,ls # tools granted to each subagent
69
+ ```
70
+
71
+ Running `/pr-review-config` with no arguments in the TUI opens an interactive settings menu that mirrors pi's `/settings` and the NERVous `/nervous:config`:
72
+
73
+ - One row per tier (`light` / `medium` / `heavy` model) plus a `subagent tools` row.
74
+ - Press Enter on a tier to pick a model from a searchable list (or `(unset — pi default)`); Enter/Space on `subagent tools` cycles presets.
75
+ - Selections apply and persist **immediately**; Esc closes the menu.
76
+ - Type to search, and tab-completion is available for the `key=value` form.
77
+
78
+ Outside the TUI (or with `show`), the command posts a Markdown summary table of your settings and the effective values instead.
79
+
80
+ A `<spec>` is any pi model pattern, e.g. `provider/model` or `provider/model:high` (with a thinking level). The mapping is stored in:
81
+
82
+ - **User:** `~/.pi/agent/pr-review.json`
83
+ - **Project:** `<repo>/.pi/pr-review.json` (overlays user config; only read when the project is trusted)
84
+
85
+ Example `pr-review.json`:
86
+
87
+ ```json
88
+ {
89
+ "tiers": {
90
+ "light": "<fast-model-spec>",
91
+ "medium": "<balanced-model-spec>",
92
+ "heavy": "<strong-model-spec:high>"
93
+ },
94
+ "tools": ["read", "bash", "grep", "find", "ls"]
95
+ }
96
+ ```
97
+
98
+ Each tier runs in an **isolated `pi` subprocess** on its configured model. The `review_subagents` batch tool runs independent passes concurrently (default `max_parallel: 4`, capped at 6) and returns ordered per-pass results; the older single-pass `review_subagent` tool remains available as a compatibility fallback. If a tier is unset, that subagent falls back to the nearest configured tier, then to your pi default model.
99
+
100
+ ### 2. The orchestrator / fallback model
101
+
102
+ The orchestrator (which fetches the PR, merges findings, and emits the JSON) and the inline-fallback path both run on your pi session model:
103
+
104
+ - **Per run:** `pi --model <model-id> "/pr-review 123"`
105
+ - **Persistent default (user):** `~/.pi/agent/settings.json` → `{ "defaultModel": "<model-id>", "defaultThinkingLevel": "high" }`
106
+ - **Persistent default (project):** the same keys in `.pi/settings.json`
107
+ - **Switch mid-session:** `/model`, or `Ctrl+P` to cycle.
108
+
109
+ ## Usage
110
+
111
+ Type `/` in the pi editor and pick `pr-review`, or:
112
+
113
+ ```
114
+ /pr-review 123 # analysis only — prints the JSON report, no GitHub writes
115
+ /pr-review 123 --comment # also posts inline review comments to the PR
116
+ /pr-review 123 --include-closed # review a closed/merged PR without a confirmation prompt
117
+ /pr-review 123 --review-closed --comment # review/comment on a closed/merged PR when GitHub accepts it
118
+ ```
119
+
120
+ `123` is the PR number in the current repo.
121
+
122
+ ### Closed or merged PRs
123
+
124
+ Closed/merged PRs no longer hard-skip. If you run `/pr-review 123` on a non-open PR, the prompt asks whether to continue before producing a review. Use `--include-closed` or `--review-closed` to proceed non-interactively. If `--comment` is also used and GitHub rejects inline comments on the non-open PR, findings should be folded into the summary comment instead.
125
+
126
+ ### Duplicate review handling
127
+
128
+ `--comment` summary comments include a hidden `pi-pr-review` marker with the reviewed `headRefOid`. A later run skips only when it finds a marker for the **current** head SHA. If new commits were pushed after the previous review, the head SHA changes and `/pr-review` reviews the PR again. Older unmarked comments are treated as unknown/stale, not proof that the current head was already reviewed.
129
+
130
+ ### Response format
131
+
132
+ For actual review output, the assistant replies with **only** the JSON object (no prose, no fences). The only exception is the pre-review confirmation question for closed/merged PRs when `--include-closed` / `--review-closed` was not supplied.
133
+
134
+ In the **interactive TUI**, the final JSON is rendered as a full review: a `## Code Review — PR #N: <title>` header, a **Verification** line, **Overview**, **Strengths**, a **Findings** table (sorted `P0 → nit`, with a blocking column, location, and confidence) plus per-finding details, **Correctness / Security / Performance** notes, and a **Verdict**. In `print` / `json` / `rpc` modes the raw JSON is left untouched so piping and automation keep a machine-readable payload.
135
+
136
+ Example payload:
137
+
138
+ ```json
139
+ {
140
+ "pr": { "number": 33, "title": "fix(logs): parse date-time log timestamps" },
141
+ "verification": "`go build ./...` ✅, `go test ./...` ✅ (130 passed)",
142
+ "overview": "Migrates log timestamps from epoch-ms to RFC3339 to match the endpoint contract.",
143
+ "strengths": ["Reuses FormatTimestamp instead of ad-hoc formatting; net -3 lines."],
144
+ "findings": [
145
+ {
146
+ "title": "[P1] Guard against nil map before write",
147
+ "severity": "P1",
148
+ "blocking": true,
149
+ "body": "Panics under concurrent writes; guard with a mutex.",
150
+ "confidence_score": 0.9,
151
+ "code_location": {
152
+ "absolute_file_path": "pkg/store/cache.go",
153
+ "line_range": { "start": 42, "end": 45 },
154
+ "side": "RIGHT",
155
+ "commentable": true
156
+ }
157
+ }
158
+ ],
159
+ "notes": { "correctness": "build confirms; no unused imports", "security": "none", "performance": "negligible" },
160
+ "verdict": "approve",
161
+ "overall_correctness": "patch is correct",
162
+ "overall_explanation": "Clean, well-scoped contract-alignment change with matching tests.",
163
+ "overall_confidence_score": 0.9
164
+ }
165
+ ```
166
+
167
+ Severity tags: `[P0]` blocking/drop-everything · `[P1]` blocking/urgent · `[P2]` normal · `[P3]` low · `[nit]` trivial/optional. Verdict is `approve` (no blocking findings), `request_changes` (a blocking finding exists), or `comment`.
168
+
169
+ **Inline-comment ready.** Each finding's `code_location` is diff-anchored — repo-relative `absolute_file_path`, `line_range` on `side` (`RIGHT` for added/context lines, `LEFT` for removed), and `commentable` (whether the lines are inside a diff hunk). The rendered table shows an **Inline** ✎ column for findings that can be posted as GitHub inline review comments. With `--comment`, a summary review is posted plus inline comments (single- or multi-line, using each finding's anchor) for every commentable blocking/P2/P3 finding; nits and off-diff/repo-wide observations fold into the summary.
170
+
171
+ ## What's in the package
172
+
173
+ ```
174
+ pi-pr-review/
175
+ ├─ package.json # pi manifest: prompts + extensions
176
+ ├─ prompts/pr-review.md # the /pr-review orchestrator prompt
177
+ ├─ extensions/pr-review-subagent.ts # review_subagents/review_subagent tools + /pr-review-config command
178
+ └─ extensions/review-table.ts # renders the final JSON as a table (TUI only)
179
+ ```
180
+
181
+ ## Security & cost notes
182
+
183
+ - The `review_subagents` batch tool and `review_subagent` fallback spawn isolated `pi` subprocesses (`--mode json -p --no-session`) on your configured tier models. Subagents are read-only reviewers (`read,bash,grep,find,ls` by default) and never post comments or edit files.
184
+ - Project-local `pr-review.json` is only read when the project is trusted.
185
+ - Tiered review calls multiple models per PR, now concurrently for independent passes. Point `light` at a cheap model for overview/risk scan; reserve `heavy` for the deep passes.
186
+
187
+ ## Design notes
188
+
189
+ - **Process** mirrors the Claude review workflow (PR-number driven, confirm-before-reviewing closed/merged PRs, skip draft/same-head-already-reviewed, overview + strengths, convention/readability/maintainability, best-effort build/test verification, validate-then-classify, optional comment posting with strict GitHub permalink rules) with bounded parallel multi-model fan-out (configurable light/medium/heavy tiers).
190
+ - **Captures every severity** (`nit → P0`) with a `blocking` flag; the verdict depends only on blocking findings, so nothing minor is lost but a clean PR still gets approved.
191
+ - **Verification is non-destructive:** any build/test runs in an isolated `git worktree` on the PR head — the prompt never checks out, commits, or pushes in your working tree.
192
+ - pi has no built-in sub-agents, so tiering is implemented as an extension that spawns isolated `pi` subprocesses per tier; the batch tool gives deterministic parallelism, and the prompt degrades gracefully to single-pass or inline review when the extension is absent.