@vintasoftware/pr-review-canvas 0.4.0 → 0.5.0
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 +27 -8
- package/docs/reference.md +247 -62
- package/package.json +1 -1
- package/pr-review.config.example.yml +38 -4
- package/prompts/generation-format.md +120 -26
- package/prompts/generation-strict-incremental.md +53 -0
- package/prompts/generation-strict.md +1 -27
- package/prompts/generation-surfacing-incremental.md +56 -0
- package/prompts/generation-surfacing.md +1 -58
- package/prompts/judging-strict.md +27 -0
- package/prompts/judging-surfacing.md +58 -0
- package/skills/pr-review-canvas/SKILL.md +13 -4
- package/src/acpx/acpx.ts +98 -5
- package/src/acpx/models.ts +43 -0
- package/src/chat/chat-manager.ts +27 -1
- package/src/cli.ts +58 -1
- package/src/commands.ts +5 -1
- package/src/contract/api.ts +26 -1
- package/src/contract/canvas-manifest.ts +5 -0
- package/src/contract/generation-context.ts +52 -1
- package/src/contract/keys.ts +1 -0
- package/src/contract/pending.ts +49 -0
- package/src/contract/review-artifact.ts +50 -7
- package/src/contract/reviews.ts +10 -1
- package/src/contract/settings.ts +5 -0
- package/src/contract/state.ts +23 -12
- package/src/contract/validation.ts +1 -0
- package/src/github/post-review.ts +62 -6
- package/src/gitlab/post-review.ts +48 -9
- package/src/gitlab/publish-drafts.ts +69 -0
- package/src/host/client.ts +3 -2
- package/src/host/host.ts +23 -5
- package/src/project-config.ts +15 -2
- package/src/review/carry-marks.ts +131 -0
- package/src/review/doctor.ts +60 -26
- package/src/review/incremental.ts +107 -0
- package/src/review/normalize.ts +14 -4
- package/src/review/prepare.ts +47 -0
- package/src/review/prompt.ts +112 -5
- package/src/review/publish.ts +1 -0
- package/src/review/test-paths.ts +44 -4
- package/src/review/validate-folds.ts +348 -23
- package/src/review/validate.ts +10 -1
- package/src/server/bundle.ts +14 -2
- package/src/server/html.ts +4 -4
- package/src/server/routes/chat-routes.ts +15 -6
- package/src/server/routes/pages.ts +4 -1
- package/src/server/routes/review-routes.ts +202 -42
- package/src/store/canvas-store.ts +3 -0
- package/src/store/settings-store.ts +9 -1
- package/src/store/state-store.ts +69 -4
- package/src/upgrade.ts +338 -0
- package/static/js/api.js +55 -1
- package/static/js/app.js +28 -7
- package/static/js/chat-panel.js +32 -9
- package/static/js/chat.js +27 -4
- package/static/js/code-folds.js +171 -44
- package/static/js/composer.js +109 -4
- package/static/js/contract-types.d.ts +4 -0
- package/static/js/diff-decorations.js +67 -1
- package/static/js/empty-state.js +17 -0
- package/static/js/fold-levels.js +176 -0
- package/static/js/header.js +36 -9
- package/static/js/interactions.js +273 -44
- package/static/js/keyboard.js +4 -1
- package/static/js/keys.js +12 -0
- package/static/js/layers.js +292 -29
- package/static/js/nav.js +22 -4
- package/static/js/pending.js +161 -0
- package/static/js/points.js +69 -9
- package/static/js/progress.js +4 -5
- package/static/js/quick-questions.js +15 -2
- package/static/js/reading-level.js +97 -0
- package/static/js/review-session.js +106 -27
- package/static/js/settings.js +53 -23
- package/static/js/signoff.js +75 -5
- package/static/js/skin.js +2 -2
- package/static/styles/chat-panel.css +22 -24
- package/static/styles/chat.css +4 -0
- package/static/styles/header.css +21 -0
- package/static/styles/pending.css +102 -0
- package/static/styles/review.css +4 -0
- package/static/styles.css +1 -0
package/README.md
CHANGED
|
@@ -63,6 +63,18 @@ Install the command globally once, for use in any project:
|
|
|
63
63
|
npm install -g @vintasoftware/pr-review-canvas
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### Upgrade
|
|
67
|
+
|
|
68
|
+
Run this from a project that has the skill installed:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pr-review upgrade
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
It updates pr-review, acpx, and the project's skill copies, after showing the plan and asking.
|
|
75
|
+
Commit and push any refreshed skill copies so your team uses the same skill. `--yes` skips the
|
|
76
|
+
question.
|
|
77
|
+
|
|
66
78
|
## Set up a project
|
|
67
79
|
|
|
68
80
|
```bash
|
|
@@ -73,9 +85,8 @@ pr-review doctor --all-checks
|
|
|
73
85
|
|
|
74
86
|
`install-skill` sets up **both Claude Code and Codex** in one command: `.claude/skills/pr-review-canvas`
|
|
75
87
|
and `.agents/skills/pr-review-canvas`, respectively. These are portable copies you can commit to Git.
|
|
76
|
-
|
|
77
|
-
project's `.gitignore`. Restart your coding agent if the skill
|
|
78
|
-
does not appear. Repeat this setup for each project you want to review.
|
|
88
|
+
`pr-review upgrade` refreshes them after the CLI changes. It also adds `.pr-review/settings.yml` to the
|
|
89
|
+
project's `.gitignore`. Restart your coding agent if the skill does not appear. Repeat this setup for each project you want to review.
|
|
79
90
|
|
|
80
91
|
`doctor` checks Git, your GitHub or GitLab remote, the matching CLI (`gh` or `glab`) and its login,
|
|
81
92
|
write access to the local canvas directory, and whether installed skills match the current package.
|
|
@@ -91,7 +102,7 @@ or modified. The warning includes the reinstall command and does not block start
|
|
|
91
102
|
To ask questions about a PR inside the canvas, install `acpx` globally:
|
|
92
103
|
|
|
93
104
|
```bash
|
|
94
|
-
npm install -g acpx
|
|
105
|
+
npm install -g acpx@latest
|
|
95
106
|
acpx --version
|
|
96
107
|
pr-review doctor --all-checks
|
|
97
108
|
```
|
|
@@ -131,17 +142,25 @@ merged `main` in without touching the changed files, for example, the canvas sti
|
|
|
131
142
|
and the page says so. Set `canvas.keepForIdenticalDiff: false` in the project config to treat
|
|
132
143
|
every commit as a new head.
|
|
133
144
|
|
|
145
|
+
Regenerating for a new head updates the previous canvas. Content for untouched files is kept,
|
|
146
|
+
and your review progress on them follows. `--force` starts from a blank page, and
|
|
147
|
+
`canvas.incremental: false` turns this off. See [Incremental canvases](docs/reference.md#incremental-canvases).
|
|
148
|
+
|
|
134
149
|
## Configuration
|
|
135
150
|
|
|
136
151
|
### User-local preferences
|
|
137
152
|
|
|
138
|
-
Your appearance and AI Chat preferences are saved in `.pr-review/settings.yml`
|
|
139
|
-
project directory. This file is ignored by Git, so each teammate can use their own
|
|
153
|
+
Your appearance, reading level, and AI Chat preferences are saved in `.pr-review/settings.yml`
|
|
154
|
+
in your local project directory. This file is ignored by Git, so each teammate can use their own
|
|
155
|
+
settings.
|
|
140
156
|
|
|
141
|
-
Use **skin** and **theme** in the header to change the appearance
|
|
157
|
+
Use **skin** and **theme** in the header to change the appearance, and **Hide code by default**
|
|
158
|
+
in the settings dialog to choose how much code a review hides when it opens.
|
|
142
159
|
|
|
143
160
|
For AI Chat, open **settings**, choose Claude Code or Codex, and optionally enter a model ID.
|
|
144
|
-
Leave the model blank to use the agent's default.
|
|
161
|
+
Leave the model blank to use the agent's default. A model ID runs as the newest model of its family
|
|
162
|
+
(`claude-opus-4-8` runs as `opus`); write `pin:claude-opus-4-8` to use that exact model. See
|
|
163
|
+
[Model families](docs/reference.md#model-families). You can also adjust the reply timeout and
|
|
145
164
|
maximum turns. Click **Test agent** to check the connection, then **save**.
|
|
146
165
|
|
|
147
166
|
Switching agents starts a new thread and keeps earlier threads. Server flags `--agent` and
|
package/docs/reference.md
CHANGED
|
@@ -15,15 +15,15 @@ For setup and the basic review workflow, see the [README](../README.md).
|
|
|
15
15
|
|
|
16
16
|
### Repository and runtime options
|
|
17
17
|
|
|
18
|
-
| Option | Applies to
|
|
19
|
-
| -------------------------------- |
|
|
20
|
-
| `--repo <dir>` | All commands
|
|
21
|
-
| `--data-dir <dir>` | All except `install-skill` | Overrides `PR_REVIEW_DATA_DIR`, then the default `<main checkout>/.pr-review` |
|
|
22
|
-
| `--port <n>` | `serve`
|
|
23
|
-
| `--agent claude\|codex` | `serve`
|
|
24
|
-
| `--model <id>` | `serve`
|
|
25
|
-
| `--fixture-canvas <review.json>` | `serve`
|
|
26
|
-
| `PR_REVIEW_HOST=gitlab` | Environment
|
|
18
|
+
| Option | Applies to | Default and behavior |
|
|
19
|
+
| -------------------------------- | ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `--repo <dir>` | All commands | Uses the current directory when omitted; resolves the repository root from there |
|
|
21
|
+
| `--data-dir <dir>` | All except `install-skill` and `upgrade` | Overrides `PR_REVIEW_DATA_DIR`, then the default `<main checkout>/.pr-review` |
|
|
22
|
+
| `--port <n>` | `serve` | Overrides `PR_REVIEW_PORT`, then `3010`; accepts 1–65535 |
|
|
23
|
+
| `--agent claude\|codex` | `serve` | Overrides the saved chat agent for this run |
|
|
24
|
+
| `--model <id>` | `serve` | Overrides the saved chat model for this run |
|
|
25
|
+
| `--fixture-canvas <review.json>` | `serve` | Development preview: uses the supplied canvas for every requested PR, with its head replaced by the live PR head |
|
|
26
|
+
| `PR_REVIEW_HOST=gitlab` | Environment | Treats a non-github.com origin as GitLab (self-hosted hosts whose name does not contain `gitlab`) |
|
|
27
27
|
|
|
28
28
|
Repository operations require an `origin` remote on **github.com** or **GitLab** (gitlab.com, a
|
|
29
29
|
hostname that contains `gitlab`, or any host with `PR_REVIEW_HOST=gitlab`). GitHub Enterprise Server
|
|
@@ -91,7 +91,9 @@ pr-review prepare --base origin/main --head HEAD
|
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
`validate` checks the supplied file against the context in `--canvas`. By default it returns
|
|
94
|
-
`{ ok, errors }`; `--human` prints readable diagnostics.
|
|
94
|
+
`{ ok, errors }`; `--human` prints readable diagnostics. A `review.json` is checked for
|
|
95
|
+
correctness only. The folding rules (`FOLD_MISSING`, a test file collapsed at `light`) apply only
|
|
96
|
+
to a `model.json`, because older canvases predate them. `--fix` edits overlong titles by removing
|
|
95
97
|
the explanation after the first `:` or `—` and reports the changes. Titles that still exceed the
|
|
96
98
|
limit and overlong prose require rewriting.
|
|
97
99
|
|
|
@@ -188,14 +190,45 @@ Each installed `SKILL.md` records `metadata.body-sha256` in its YAML frontmatter
|
|
|
188
190
|
covers the body after the closing frontmatter delimiter, with CRLF normalized to LF. `doctor`
|
|
189
191
|
compares the recorded hash and actual body against the skill bundled with the running CLI. Any
|
|
190
192
|
outdated or modified copy in `.claude/skills` or `.agents/skills` fails the skill check, even if the
|
|
191
|
-
other copy is current. Refresh copies with `pr-review install-skill` (repeat
|
|
192
|
-
flags used during installation). Automatic discovery checks the two default directories.
|
|
193
|
+
other copy is current. Refresh copies with `pr-review upgrade` or `pr-review install-skill` (repeat
|
|
194
|
+
any custom directory flags used during installation). Automatic discovery checks the two default directories.
|
|
193
195
|
|
|
194
196
|
`serve` runs this skill check automatically and prints failures with a repair hint to stderr.
|
|
195
197
|
Warnings do not prevent the server from starting. Use `doctor --all-checks` for full diagnostics.
|
|
196
198
|
The `.gitignore` update always applies to the selected repository root, even with custom skill
|
|
197
199
|
directories.
|
|
198
200
|
|
|
201
|
+
### Upgrade options
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
pr-review upgrade [--yes] [--only package,acpx,skill] [--repo <dir>]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`upgrade` checks three things, prints a plan to stderr, and asks `Proceed? [y/N]`:
|
|
208
|
+
|
|
209
|
+
| What | When it changes | How |
|
|
210
|
+
| ----------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
211
|
+
| pr-review | npm has a newer version, and this copy is the global npm install | `npm install -g @vintasoftware/pr-review-canvas@<version>` |
|
|
212
|
+
| acpx | npm has a newer version, and the acpx on PATH is the global npm install | `npm install -g acpx@<version>` |
|
|
213
|
+
| The project skill | A copy in `.claude/skills` or `.agents/skills` differs from the bundled one | The same copy `install-skill` makes |
|
|
214
|
+
|
|
215
|
+
When pr-review itself upgrades, the skill step covers every copy, since the new version may ship
|
|
216
|
+
a new skill. After installing, it runs the new version as `pr-review upgrade --yes --only <kinds>`
|
|
217
|
+
with the confirmed steps, so the new version copies its own skill and takes only the steps the plan
|
|
218
|
+
showed. If the install fails, the current version runs the remaining steps itself.
|
|
219
|
+
|
|
220
|
+
- `--only` limits the run to the named kinds. Skipped kinds are listed in `notes`.
|
|
221
|
+
- `upgrade` does not install a missing acpx or add a missing skill copy. It prints the command
|
|
222
|
+
that does.
|
|
223
|
+
- An unmanaged skill directory is left alone; replace it with `install-skill --force`.
|
|
224
|
+
- A pr-review run from a clone or through `npx` is left alone, with a note to update it the way it
|
|
225
|
+
was installed.
|
|
226
|
+
|
|
227
|
+
Without a terminal, `upgrade` prints the plan and changes nothing. `--yes` applies it without
|
|
228
|
+
asking. stdout is one JSON line with `applied` and, after applying, `ok` and each step's `status`
|
|
229
|
+
(`done` or `failed`, with a `detail`). The exit code is `1` when a step fails. When a skill copy
|
|
230
|
+
changes, stderr says to commit and push it.
|
|
231
|
+
|
|
199
232
|
### Output and exit codes
|
|
200
233
|
|
|
201
234
|
One-shot commands normally print a JSON result on stdout. Preparation progress goes to stderr.
|
|
@@ -224,21 +257,22 @@ Lists you supply replace their defaults.
|
|
|
224
257
|
Path patterns match repository-relative paths. `**` crosses directories; `*` and `?` match
|
|
225
258
|
within one path segment.
|
|
226
259
|
|
|
227
|
-
| Key | Default
|
|
228
|
-
| ------------------------------- |
|
|
229
|
-
| `version` | `1`
|
|
230
|
-
| `rulebook` | Unset
|
|
231
|
-
| `layers` | `[]`
|
|
232
|
-
| `highRisk` | `[]`
|
|
233
|
-
| `generation.mode` | `strict`
|
|
234
|
-
| `generation.maxRepairRounds` | `3`
|
|
235
|
-
| `generation.inlineDiffMaxLines` | `1500`
|
|
236
|
-
| `generation.smallPrHunks` | `10`
|
|
237
|
-
| `generation.caps` | See below
|
|
238
|
-
| `tests.patterns` |
|
|
239
|
-
| `chat.enabled` | `true`
|
|
240
|
-
| `canvas.keepForIdenticalDiff` | `true`
|
|
241
|
-
| `
|
|
260
|
+
| Key | Default | Details |
|
|
261
|
+
| ------------------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
262
|
+
| `version` | `1` | The only supported configuration version |
|
|
263
|
+
| `rulebook` | Unset | Path to a Markdown file of project code standards, resolved from the repository root; these standards take precedence over bundled standards |
|
|
264
|
+
| `layers` | `[]` | Optional review guidance; each entry has `id`, `title`, `description`, and optional `paths` patterns. The agent may combine, split, or reorder groups. When omitted or empty, it chooses semantic sections from the change |
|
|
265
|
+
| `highRisk` | `[]` | Entries with a `pattern` glob and `label`; matching changes receive risk labels and cannot go in the Other layer |
|
|
266
|
+
| `generation.mode` | `strict` | See [generation modes](#generation-modes) |
|
|
267
|
+
| `generation.maxRepairRounds` | `3` | Failed validation rounds allowed by the generation skill |
|
|
268
|
+
| `generation.inlineDiffMaxLines` | `1500` | Maximum diff length to include directly in the generation prompt |
|
|
269
|
+
| `generation.smallPrHunks` | `10` | At or below this hunk count, the prompt asks for one layer unless concerns differ |
|
|
270
|
+
| `generation.caps` | See below | Overrides individual text limits |
|
|
271
|
+
| `tests.patterns` | Test directories and file-name shapes across stacks; see the example config | Paths treated as tests for review ordering, labels, and the light reading level |
|
|
272
|
+
| `chat.enabled` | `true` | Set to `false` to disable AI Chat |
|
|
273
|
+
| `canvas.keepForIdenticalDiff` | `true` | Keep the canvas current for a later head whose diff is identical to the canvas's; see [outdated canvases](#outdated-canvases). Set to `false` to mark it outdated on every commit |
|
|
274
|
+
| `canvas.incremental` | `true` | Regenerate a canvas for a new head by updating the newest canvas of a commit the head was built on; see [incremental canvases](#incremental-canvases). Set to `false` to generate every canvas from a blank page |
|
|
275
|
+
| `prompts` | Bundled templates | See [prompt templates](#prompt-templates) for supported keys and behavior |
|
|
242
276
|
|
|
243
277
|
Generation's numeric options and text caps must be positive integers. An empty `layers` list
|
|
244
278
|
provides no suggested groups; an empty `tests.patterns` list recognizes no files as tests.
|
|
@@ -259,14 +293,18 @@ affects canvas generation; chat answers the reviewer's selected question.
|
|
|
259
293
|
|
|
260
294
|
The `prompts` map in `pr-review.config.yml` accepts these keys:
|
|
261
295
|
|
|
262
|
-
| Key
|
|
263
|
-
|
|
|
264
|
-
| `generation-format.md`
|
|
265
|
-
| `generation-strict.md`
|
|
266
|
-
| `generation-surfacing.md`
|
|
267
|
-
| `
|
|
268
|
-
| `
|
|
269
|
-
| `
|
|
296
|
+
| Key | Purpose |
|
|
297
|
+
| ------------------------------------- | ----------------------------------------------------------- |
|
|
298
|
+
| `generation-format.md` | Schema and output rules |
|
|
299
|
+
| `generation-strict.md` | Instructions for strict mode |
|
|
300
|
+
| `generation-surfacing.md` | Instructions for surfacing mode |
|
|
301
|
+
| `generation-strict-incremental.md` | Strict mode, updating an existing canvas |
|
|
302
|
+
| `generation-surfacing-incremental.md` | Surfacing mode, updating an existing canvas |
|
|
303
|
+
| `judging-strict.md` | Strict mode's judging rules, shared by both of its tasks |
|
|
304
|
+
| `judging-surfacing.md` | Surfacing mode's judging rules, shared by both of its tasks |
|
|
305
|
+
| `quality-standards.md` | Bundled code standards |
|
|
306
|
+
| `layering-guidance.md` | Guidance for grouping related changes |
|
|
307
|
+
| `chat-seed.md` | Opening AI Chat instructions |
|
|
270
308
|
|
|
271
309
|
Each configured file replaces a whole template. Paths resolve from the project root,
|
|
272
310
|
including when running from a subdirectory or using `--repo`. Absolute paths work for
|
|
@@ -324,19 +362,54 @@ placed in Other while its source is in a regular layer.
|
|
|
324
362
|
|
|
325
363
|
The data directory's `settings.yml` accepts these keys and values:
|
|
326
364
|
|
|
327
|
-
| Key | Default
|
|
328
|
-
| ---------------- |
|
|
329
|
-
| `version` | `1`
|
|
330
|
-
| `skin` | `
|
|
331
|
-
| `theme` | `auto`
|
|
332
|
-
| `
|
|
333
|
-
| `
|
|
334
|
-
| `
|
|
335
|
-
| `
|
|
365
|
+
| Key | Default | Accepted values |
|
|
366
|
+
| ---------------- | -------- | ------------------------------------------------- |
|
|
367
|
+
| `version` | `1` | `1` |
|
|
368
|
+
| `skin` | `github` | `terminal`, `github` |
|
|
369
|
+
| `theme` | `auto` | `auto`, `light`, `dark` |
|
|
370
|
+
| `foldLevel` | `light` | `light`, `moderate`, `aggressive` |
|
|
371
|
+
| `agent` | `claude` | `claude`, `codex` |
|
|
372
|
+
| `model` | `null` | A model ID, or `null` for the agent's default (1) |
|
|
373
|
+
| `chatTimeoutSec` | `600` | Integer seconds, 30–3600 |
|
|
374
|
+
| `maxTurns` | `null` | Integer 1–100, or `null` for the agent's default |
|
|
375
|
+
|
|
376
|
+
(1) A model ID names a family; see [Model families](#model-families).
|
|
336
377
|
|
|
337
378
|
Invalid settings fall back to defaults. URL parameters `?skin=github&theme=light` can override
|
|
338
379
|
appearance for one page load without saving it.
|
|
339
380
|
|
|
381
|
+
#### Model families
|
|
382
|
+
|
|
383
|
+
Each chat turn runs the newest model of the saved model's family. A trailing `[...]`, such as
|
|
384
|
+
`[1m]` or `[high]`, is kept.
|
|
385
|
+
|
|
386
|
+
- **Claude:** an Anthropic model ID becomes its family alias, which the `claude` CLI resolves to
|
|
387
|
+
its newest model. `claude-opus-4-8[1m]` runs as `opus[1m]`, and `claude-haiku-4-5-20251001` runs
|
|
388
|
+
as `haiku`.
|
|
389
|
+
- **Codex:** a GPT model follows the `upgrade` links in the Codex model catalog
|
|
390
|
+
(`codex debug models`) to the model that replaced it, even under a new name: `gpt-5.6-terra` runs
|
|
391
|
+
as `gpt-6-sol`. A model with no `upgrade` link runs as saved.
|
|
392
|
+
- **Blank model:** the agent's default applies. A thread still on a replaced model moves to its
|
|
393
|
+
replacement.
|
|
394
|
+
|
|
395
|
+
To pin an exact version, prefix the ID with `pin:`. The ID is then sent as written, for either
|
|
396
|
+
agent:
|
|
397
|
+
|
|
398
|
+
| Agent | Example | Runs |
|
|
399
|
+
| ------ | ------------------------- | -------------------------- |
|
|
400
|
+
| Claude | `pin:claude-opus-4-8` | Opus 4.8 |
|
|
401
|
+
| Codex | `pin:gpt-5.6-terra[high]` | GPT-5.6 Terra, high effort |
|
|
402
|
+
|
|
403
|
+
The agent must still offer the model. Claude Code refuses some combinations, for example
|
|
404
|
+
`claude-opus-4-8[1m]`, and the turn fails with the agent's error.
|
|
405
|
+
|
|
406
|
+
Bedrock and Vertex Claude IDs, such as `us.anthropic.claude-opus-4-8-v1:0` or
|
|
407
|
+
`claude-opus-4-8@20260801`, run as written without `pin:`. They work only when Claude Code is set
|
|
408
|
+
up for that provider, for example with `CLAUDE_CODE_USE_BEDROCK=1` or `CLAUDE_CODE_USE_VERTEX=1`.
|
|
409
|
+
|
|
410
|
+
Claude chat runs the `claude` CLI on PATH, or the Claude Code bundled with acpx when there is none.
|
|
411
|
+
To use another binary, set `CLAUDE_CODE_EXECUTABLE` before `pr-review serve`.
|
|
412
|
+
|
|
340
413
|
By default, Git worktrees of the same clone share the main checkout's data directory. Separate
|
|
341
414
|
clones have separate data. An explicit data-directory override also relocates `settings.yml`,
|
|
342
415
|
canvases, review progress, and chat history.
|
|
@@ -370,6 +443,47 @@ start collapsed. Click the summary to expand them. Moves are detected within a f
|
|
|
370
443
|
between files appear as deletions and additions. Edited moves keep their changed text visible.
|
|
371
444
|
Collapsing content does not mark it reviewed.
|
|
372
445
|
|
|
446
|
+
### Reading levels
|
|
447
|
+
|
|
448
|
+
The **Hide code** control, beside the review progress, sets how much of the canvas is hidden. The
|
|
449
|
+
levels nest: whatever `light` hides, `moderate` and `aggressive` hide too. The generator gives each
|
|
450
|
+
fold and each collapsed file the lowest level at which it hides.
|
|
451
|
+
|
|
452
|
+
| Level | What it hides |
|
|
453
|
+
| ------------ | ---------------------------------------------------------------------------------------- |
|
|
454
|
+
| `light` | Imports, whitespace, moves, and wholly generated files (the default) |
|
|
455
|
+
| `moderate` | Also test bodies under their titles, helpers, adapters, boilerplate, mappings and wiring |
|
|
456
|
+
| `aggressive` | Also any block its title explains, so the change reads as pseudo-code |
|
|
457
|
+
|
|
458
|
+
The control shows what the chosen level hides and how many lines that is. Each layer shows its count
|
|
459
|
+
in its Files heading, and the sign-off dialog records the total.
|
|
460
|
+
|
|
461
|
+
The page opens at `foldLevel` from `settings.yml` (`light` by default), which the **Hide code by
|
|
462
|
+
default** field in the settings dialog sets. The control and the `f` key change the level for the
|
|
463
|
+
current page only. Changing the level redraws the visible diffs and re-applies file collapse,
|
|
464
|
+
including cards opened by hand.
|
|
465
|
+
|
|
466
|
+
These always stay visible:
|
|
467
|
+
|
|
468
|
+
- Attention points, comment threads, and pending review drafts. A file with a thread or a draft
|
|
469
|
+
folds nothing.
|
|
470
|
+
- Files with an annotation or an attention point. They never collapse whole.
|
|
471
|
+
- Annotations, except under an `aggressive` fold that covers the whole annotation and no other. That
|
|
472
|
+
fold shows the annotation's text instead of its title.
|
|
473
|
+
- Test files at `light`, except snapshots and fixtures. From `moderate`, each test body folds under
|
|
474
|
+
its own title, or the file collapses whole.
|
|
475
|
+
|
|
476
|
+
Validation fails with `FOLD_MISSING` when the generator hides too little:
|
|
477
|
+
|
|
478
|
+
- A file with more than 20 changed lines outside its annotations and no attention point hides
|
|
479
|
+
nothing at any level.
|
|
480
|
+
- An open file over 60 lines folds less than half of its lines outside attention points by
|
|
481
|
+
`aggressive`. Annotated lines count, since an aggressive fold may hide them.
|
|
482
|
+
- A layer over 100 changed lines leaves more than 20 lines open at `moderate` (outside attention
|
|
483
|
+
points) and hides nothing more at `aggressive`. Smaller layers only need to pass the file rules.
|
|
484
|
+
|
|
485
|
+
A `light` fold may cover at most 40 lines of generated content.
|
|
486
|
+
|
|
373
487
|
Files with patches longer than 2,000 lines wait behind **show diff**. A link into the file opens
|
|
374
488
|
it automatically.
|
|
375
489
|
|
|
@@ -393,13 +507,56 @@ zone or `pr-review import <zip> --pr <n>`.
|
|
|
393
507
|
|
|
394
508
|
You can post inline comments, replies, PR-level comments, and attention points. Inline comments
|
|
395
509
|
must target lines in the diff. Posting uses your `gh` or `glab` account and remains subject to its
|
|
396
|
-
repository permissions.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
510
|
+
repository permissions.
|
|
511
|
+
|
|
512
|
+
Click a line number to comment on one line. Shift-click a second line number, or drag across a
|
|
513
|
+
range, to select several lines: the comment then covers the whole range, and posts as a multi-line
|
|
514
|
+
comment (`start_line` on GitHub, a `line_range` position on GitLab). A range must stay inside one
|
|
515
|
+
chunk of the diff.
|
|
516
|
+
|
|
517
|
+
### Pending reviews
|
|
518
|
+
|
|
519
|
+
A pending review holds comments on your machine until you submit them together.
|
|
520
|
+
|
|
521
|
+
- **post to github** on a diff-line comment posts it at once. **start a review** adds it to a new
|
|
522
|
+
pending review instead.
|
|
523
|
+
- While a review is open, a diff-line comment can only **add review comment**, so no comment
|
|
524
|
+
publishes ahead of the review. Replies and pull-request comments are not part of a forge review,
|
|
525
|
+
so they still post at once.
|
|
526
|
+
- An attention point keeps both **post to github** and **add to review**, since its text is written
|
|
527
|
+
in advance. A point in the review shows **in your review**; edit or remove it as the draft on its
|
|
528
|
+
line. After submission, the point shows the comment it became.
|
|
529
|
+
- A bar under the progress line shows how many drafts are waiting. Each draft appears on its line
|
|
530
|
+
with a **pending** badge and edit and delete commands. Drafts are saved in the local review state
|
|
531
|
+
and survive a reload. **discard** drops the whole review; nothing was sent to the forge.
|
|
532
|
+
- Drafts from an earlier commit are listed separately in the bar with their original location and
|
|
533
|
+
commit. They are submitted only when the stored diff is identical to the current one and
|
|
534
|
+
`canvas.keepForIdenticalDiff` is on. Otherwise, copy the text, delete the draft, and comment on
|
|
535
|
+
the current code.
|
|
536
|
+
- A draft added or edited during submission stays pending.
|
|
537
|
+
|
|
538
|
+
**finish your review** opens the sign-off dialog, which shows how many drafts go out with the
|
|
539
|
+
review:
|
|
540
|
+
|
|
541
|
+
- **GitHub:** the drafts are the comments of the single call that creates the review.
|
|
542
|
+
- **GitLab:** the inline comments and summary are staged as draft notes and published in one batch.
|
|
543
|
+
Finish or discard any review already pending in GitLab first. Approval is a separate call; if it
|
|
544
|
+
fails after publication, the comments stay published and the page asks you to approve in GitLab.
|
|
545
|
+
|
|
546
|
+
A refused submission keeps the local drafts and removes the remote drafts that attempt staged.
|
|
547
|
+
|
|
548
|
+
### Sign-off
|
|
549
|
+
|
|
550
|
+
Sign-off offers three verdicts: **approve**, **request changes**, and **comment**, which posts a
|
|
551
|
+
review with no verdict. Each opens a
|
|
552
|
+
dialog previewing an editable review body summarizing reviewed layers, dismissed attention points,
|
|
553
|
+
and comments posted from the canvas, so an approval or a rejection always carries a comment.
|
|
554
|
+
|
|
555
|
+
Approval requires every layer except **Other changes** to be reviewed for the current head.
|
|
556
|
+
Requesting changes and a comment-only review do not require that completion. On GitLab,
|
|
557
|
+
**approve** calls GitLab's approve API; **request changes** and **comment** post the review body
|
|
558
|
+
as a merge request note. If the head moves before submission, reload and review the current
|
|
559
|
+
commit.
|
|
403
560
|
|
|
404
561
|
### Outdated canvases
|
|
405
562
|
|
|
@@ -423,6 +580,33 @@ same rule, so the CLI never calls a canvas stale that the page shows as current.
|
|
|
423
580
|
AI Chat also answers on an outdated canvas: it quotes the diff of the canvas's own commit, the
|
|
424
581
|
one on screen.
|
|
425
582
|
|
|
583
|
+
## Incremental canvases
|
|
584
|
+
|
|
585
|
+
When a canvas is regenerated for a new head, `pr-review prepare` starts from the **basis canvas**:
|
|
586
|
+
the newest canvas of a commit the head was built on. A canvas of a commit the head no longer
|
|
587
|
+
contains is never a basis. `--force` starts from a blank page, and `canvas.incremental: false`
|
|
588
|
+
turns this off for the project.
|
|
589
|
+
|
|
590
|
+
`prepare` compares the basis diff with the head diff file by file. A file whose patch is
|
|
591
|
+
byte-identical is untouched. The prompt tells the generator to copy, word for word:
|
|
592
|
+
|
|
593
|
+
- whole layers whose files are all untouched;
|
|
594
|
+
- in other layers, the notes, folds, annotations, and attention points of untouched files.
|
|
595
|
+
|
|
596
|
+
Everything else is decided again. The summary and risk tags are always rewritten. A carried
|
|
597
|
+
attention point keeps its kind, path, and title, so it keeps its fingerprint and any dismissal.
|
|
598
|
+
|
|
599
|
+
The canvas records only which basis it came from. Your server decides which review marks follow,
|
|
600
|
+
using the two canvases and your clone:
|
|
601
|
+
|
|
602
|
+
- A file's mark follows when the file is in both canvases, under the same layer key, with a
|
|
603
|
+
byte-identical patch.
|
|
604
|
+
- A layer's mark follows only when the layer has exactly the same files and none changed.
|
|
605
|
+
|
|
606
|
+
The canvas you marked is compared directly with the one on screen, so marks survive any number of
|
|
607
|
+
regenerations in between. When a mark follows, the page names the canvas you made it on. If your
|
|
608
|
+
machine lacks that canvas or cannot rebuild either diff, no marks follow.
|
|
609
|
+
|
|
426
610
|
## AI Chat
|
|
427
611
|
|
|
428
612
|
**Ask** on a layer, file, attention point, or line selection chooses the context for your message.
|
|
@@ -481,14 +665,15 @@ sandbox for the agent. Its access also depends on the agent's own permissions. D
|
|
|
481
665
|
|
|
482
666
|
Validation reports name the field, file, hunk, or line to fix. Common groups are:
|
|
483
667
|
|
|
484
|
-
| Codes | What to check
|
|
485
|
-
| --------------------------------------------------------------- |
|
|
486
|
-
| `SCHEMA`, `TEXT_TOO_LONG` | Required fields, types, and text limits
|
|
487
|
-
| `HUNK_UNASSIGNED`, `HUNK_DUPLICATE`, `HUNK_UNKNOWN` | Each known hunk belongs to exactly one layer
|
|
488
|
-
| `PATH_UNKNOWN`, `TEST_PATH_UNKNOWN` | Referenced files exist in the relevant diff or PR head
|
|
489
|
-
| `LAYER_EMPTY`, `LAYER_KEY_DUPLICATE` | Layers contain hunks and have unique keys
|
|
490
|
-
| `OTHER_DUPLICATE`, `OTHER_NOT_LAST`, `RISK_IN_OTHER` | At most one Other layer, last, without risk-tagged changes
|
|
491
|
-
| `TEST_NOT_LAST`, `TEST_IN_OTHER` | Tests follow the code they cover and use the appropriate layer
|
|
492
|
-
| `ANNOTATION_OUTSIDE_HUNK`, `POINT_OUTSIDE_DIFF`, `FOLD_INVALID` | Locations and fold ranges fit the assigned diff
|
|
493
|
-
| `
|
|
494
|
-
| `
|
|
668
|
+
| Codes | What to check |
|
|
669
|
+
| --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
670
|
+
| `SCHEMA`, `TEXT_TOO_LONG` | Required fields, types, and text limits |
|
|
671
|
+
| `HUNK_UNASSIGNED`, `HUNK_DUPLICATE`, `HUNK_UNKNOWN` | Each known hunk belongs to exactly one layer |
|
|
672
|
+
| `PATH_UNKNOWN`, `TEST_PATH_UNKNOWN` | Referenced files exist in the relevant diff or PR head |
|
|
673
|
+
| `LAYER_EMPTY`, `LAYER_KEY_DUPLICATE` | Layers contain hunks and have unique keys |
|
|
674
|
+
| `OTHER_DUPLICATE`, `OTHER_NOT_LAST`, `RISK_IN_OTHER` | At most one Other layer, last, without risk-tagged changes |
|
|
675
|
+
| `TEST_NOT_LAST`, `TEST_IN_OTHER` | Tests follow the code they cover and use the appropriate layer |
|
|
676
|
+
| `ANNOTATION_OUTSIDE_HUNK`, `POINT_OUTSIDE_DIFF`, `FOLD_INVALID` | Locations and fold ranges fit the assigned diff |
|
|
677
|
+
| `FOLD_MISSING` | A file over 20 unannotated lines hides something; an open file over 60 folds half; a layer over 100 hides more at aggressive |
|
|
678
|
+
| `TOO_MANY_POINTS` | Count explicit points and missing-test entries together |
|
|
679
|
+
| `LINK_UNRESOLVED`, `DIAGRAM_NODE_UNKNOWN`, `DIAGRAM_LIMIT` | Link targets, diagram node IDs, and diagram counts |
|
package/package.json
CHANGED
|
@@ -39,11 +39,41 @@ generation:
|
|
|
39
39
|
# rationale: 300
|
|
40
40
|
# diagram: 1500 # mermaid source, counted raw
|
|
41
41
|
|
|
42
|
-
# Which paths count as tests, for the layering rules
|
|
43
|
-
#
|
|
44
|
-
# (Python
|
|
42
|
+
# Which paths count as tests, for the layering rules, the `test` pill on a file card, and the
|
|
43
|
+
# light reading level, which keeps test titles on screen. The defaults below match test
|
|
44
|
+
# directories and file-name shapes across stacks (JS/TS, Python, Go, Ruby, Java, Kotlin, PHP,
|
|
45
|
+
# C#, Swift, Elixir, Dart, Rust). A list here replaces them; add `'**/spec/**'` when that
|
|
46
|
+
# directory holds tests in your repository. Snapshots and fixtures inside test paths may still
|
|
47
|
+
# hide at light, since they are generated.
|
|
45
48
|
tests:
|
|
46
|
-
patterns:
|
|
49
|
+
patterns:
|
|
50
|
+
- '**/__tests__/**'
|
|
51
|
+
- '**/tests/**'
|
|
52
|
+
- '**/test/**'
|
|
53
|
+
- '**/*.test.*'
|
|
54
|
+
- '**/*.spec.*'
|
|
55
|
+
- '**/*_test.*'
|
|
56
|
+
- '**/*_spec.*'
|
|
57
|
+
- '**/test_*.py'
|
|
58
|
+
- '**/conftest.py'
|
|
59
|
+
- '**/*Test.java'
|
|
60
|
+
- '**/*Tests.java'
|
|
61
|
+
- '**/*Test.kt'
|
|
62
|
+
- '**/*Tests.kt'
|
|
63
|
+
- '**/*Test.scala'
|
|
64
|
+
- '**/*Tests.scala'
|
|
65
|
+
- '**/*Test.groovy'
|
|
66
|
+
- '**/*Tests.groovy'
|
|
67
|
+
- '**/*Test.cs'
|
|
68
|
+
- '**/*Tests.cs'
|
|
69
|
+
- '**/*Test.fs'
|
|
70
|
+
- '**/*Tests.fs'
|
|
71
|
+
- '**/*Test.vb'
|
|
72
|
+
- '**/*Tests.vb'
|
|
73
|
+
- '**/*Test.swift'
|
|
74
|
+
- '**/*Tests.swift'
|
|
75
|
+
- '**/*Test.php'
|
|
76
|
+
- '**/*Tests.php'
|
|
47
77
|
|
|
48
78
|
chat:
|
|
49
79
|
enabled: true # false removes the chat pane and its routes
|
|
@@ -53,3 +83,7 @@ canvas:
|
|
|
53
83
|
# from, as after merging the base branch in. Set false to mark the canvas outdated on every new
|
|
54
84
|
# commit.
|
|
55
85
|
keepForIdenticalDiff: true
|
|
86
|
+
# Regenerating a canvas for a new head starts from the newest canvas of a commit the head was
|
|
87
|
+
# built on, keeping the layers, folds, notes and attention points its diff leaves untouched.
|
|
88
|
+
# Set false to generate every canvas from a blank page, as `--force` always does.
|
|
89
|
+
incremental: true
|