@vintasoftware/pr-review-canvas 0.1.0 → 0.3.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 +30 -28
- package/docs/reference.md +142 -98
- package/package.json +12 -3
- package/pr-review.config.example.yml +12 -31
- package/prompts/generation-format.md +4 -4
- package/prompts/layering-guidance.md +18 -0
- package/skills/pr-review-canvas/SKILL.md +8 -1
- package/src/acpx/acpx.ts +21 -4
- package/src/acpx/events.ts +5 -1
- package/src/acpx/ndjson.ts +3 -1
- package/src/acpx/preflight.ts +5 -1
- package/src/canvas/export.ts +11 -2
- package/src/canvas/name.ts +13 -13
- package/src/canvas/zip.ts +4 -1
- package/src/chat/chat-manager.ts +16 -3
- package/src/chat/context.ts +10 -3
- package/src/chat/seed.ts +3 -1
- package/src/cli.ts +16 -13
- package/src/commands.ts +41 -11
- package/src/config.ts +15 -3
- package/src/contract/comments.ts +3 -1
- package/src/contract/generation-context.ts +3 -1
- package/src/contract/review-artifact.ts +14 -8
- package/src/contract/state.ts +3 -1
- package/src/git/diff-collector.ts +2 -1
- package/src/git/git.ts +9 -4
- package/src/github/attachments.ts +3 -3
- package/src/github/capabilities.ts +5 -1
- package/src/github/comments.ts +6 -3
- package/src/github/gh.ts +18 -3
- package/src/github/post-comment.ts +4 -1
- package/src/github/pr.ts +4 -1
- package/src/github/threads.ts +5 -1
- package/src/project-config.ts +14 -54
- package/src/prompt-files.ts +4 -3
- package/src/review/doctor.ts +38 -10
- package/src/review/install-skill.ts +24 -28
- package/src/review/normalize.ts +3 -1
- package/src/review/prepare.ts +24 -8
- package/src/review/prompt.ts +17 -11
- package/src/review/publish.ts +15 -3
- package/src/review/skill-content.ts +20 -0
- package/src/review/trim-caps.ts +10 -6
- package/src/review/validate.ts +65 -13
- package/src/server/app.ts +12 -4
- package/src/server/bundle.ts +17 -4
- package/src/server/context.ts +14 -2
- package/src/server/errors.ts +26 -2
- package/src/server/html.ts +2 -2
- package/src/server/node-server.ts +4 -2
- package/src/server/routes/api.ts +29 -5
- package/src/server/routes/chat-routes.ts +30 -9
- package/src/server/routes/pages.ts +3 -1
- package/src/server/routes/review-routes.ts +19 -4
- package/src/server/sse.ts +3 -1
- package/src/store/atomic-json.ts +5 -1
- package/src/store/canvas-store.ts +20 -6
- package/src/store/derived-store.ts +5 -1
- package/src/store/pr-store.ts +2 -1
- package/src/store/state-store.ts +2 -1
- package/static/brand.svg +19 -0
- package/static/js/api.js +15 -3
- package/static/js/app.js +8 -2
- package/static/js/chat-panel.js +93 -0
- package/static/js/chat.js +38 -15
- package/static/js/composer.js +6 -3
- package/static/js/diagram.js +2 -1
- package/static/js/diff-decorations.js +5 -3
- package/static/js/diff-renderer.js +6 -1
- package/static/js/dom.js +5 -7
- package/static/js/empty-state.js +3 -1
- package/static/js/header.js +1 -1
- package/static/js/interactions.js +55 -15
- package/static/js/keyboard.js +7 -2
- package/static/js/layers.js +23 -11
- package/static/js/links.js +8 -2
- package/static/js/nav.js +5 -2
- package/static/js/overview.js +32 -4
- package/static/js/points.js +3 -2
- package/static/js/progress.js +2 -1
- package/static/js/proposed-comment.js +4 -1
- package/static/js/quick-questions.js +2 -1
- package/static/js/regenerate.js +4 -1
- package/static/js/settings.js +1 -1
- package/static/js/signoff.js +6 -2
- package/static/styles/base.css +16 -6
- package/static/styles/chat-panel.css +81 -0
- package/static/styles/chat-tools.css +28 -0
- package/static/styles/chat.css +1 -1
- package/static/styles/commands.css +4 -4
- package/static/styles/diff.css +1 -1
- package/static/styles/header.css +18 -4
- package/static/styles/layout.css +4 -4
- package/static/styles/responsive.css +1 -15
- package/static/styles/review.css +24 -3
- package/static/styles/skin-github.css +93 -100
- package/static/styles.css +13 -12
- package/prompts/layers-default.md +0 -13
package/README.md
CHANGED
|
@@ -43,8 +43,6 @@ Install the command globally once, for use in any project:
|
|
|
43
43
|
npm install -g @vintasoftware/pr-review-canvas
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
The npm installation command will be available after the first release.
|
|
47
|
-
|
|
48
46
|
## Set up a project
|
|
49
47
|
|
|
50
48
|
```bash
|
|
@@ -54,15 +52,19 @@ pr-review doctor --all-checks
|
|
|
54
52
|
```
|
|
55
53
|
|
|
56
54
|
`install-skill` sets up **both Claude Code and Codex** in one command: `.claude/skills/pr-review-canvas`
|
|
57
|
-
and `.agents/skills/pr-review-canvas`, respectively.
|
|
55
|
+
and `.agents/skills/pr-review-canvas`, respectively. These are portable copies you can commit to Git.
|
|
56
|
+
Re-run `pr-review install-skill` after upgrading the CLI to refresh them. It also adds `.pr-review/settings.yml` to the
|
|
58
57
|
project's `.gitignore`. Restart your coding agent if the skill
|
|
59
58
|
does not appear. Repeat this setup for each project you want to review.
|
|
60
59
|
|
|
61
60
|
`doctor` checks Git, your GitHub remote, the GitHub CLI and its login, write access to the local
|
|
62
|
-
canvas directory, and whether the
|
|
61
|
+
canvas directory, and whether installed skills match the current package. It prints a JSON report with a result for
|
|
63
62
|
each check and suggested fixes for failures. `doctor --all-checks` also checks that `acpx` runs and
|
|
64
63
|
reports its version. Exit code `0` means all checks passed.
|
|
65
64
|
|
|
65
|
+
`serve` automatically runs the skill check and warns on stderr if a skill is missing, outdated,
|
|
66
|
+
or modified. The warning includes the reinstall command and does not block startup.
|
|
67
|
+
|
|
66
68
|
### Optional: AI Chat install
|
|
67
69
|
|
|
68
70
|
To ask questions about a PR inside the canvas, install `acpx` globally:
|
|
@@ -131,45 +133,34 @@ Canvas generation follows the [skill's model rules](skills/pr-review-canvas/SKIL
|
|
|
131
133
|
|
|
132
134
|
### Project prompt templates
|
|
133
135
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
+
Customize generation and AI Chat prompts with the `prompts` map in your project's
|
|
137
|
+
`pr-review.config.yml`:
|
|
136
138
|
|
|
137
139
|
```yaml
|
|
138
140
|
prompts:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
generation-format.md: review-prompts/generation-format.md
|
|
142
|
+
generation-surfacing.md: review-prompts/generation-surfacing.md
|
|
143
|
+
chat-seed.md: review-prompts/chat-seed.md
|
|
142
144
|
```
|
|
143
145
|
|
|
144
|
-
|
|
146
|
+
Copy the installed templates to start editing (for an npm global install):
|
|
145
147
|
|
|
146
148
|
```bash
|
|
147
149
|
mkdir -p review-prompts
|
|
148
150
|
cp "$(npm root -g)/@vintasoftware/pr-review-canvas/prompts/"*.md review-prompts/
|
|
149
151
|
```
|
|
150
152
|
|
|
151
|
-
Edit the copies and
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
package's defaults; a configured file that cannot be read causes an error.
|
|
156
|
-
|
|
157
|
-
The six supported keys are `generation-format.md` (schema and output rules),
|
|
158
|
-
`generation-strict.md` and `generation-surfacing.md` (mode wrappers),
|
|
159
|
-
`quality-standards.md` (bundled code standards), `layers-default.md` (taxonomy prose),
|
|
160
|
-
and `chat-seed.md` (the opening AI Chat instructions). `generation.mode` still selects
|
|
161
|
-
the wrapper. The rulebook still takes precedence over code standards, and configured
|
|
162
|
-
layers and caps still supply the template data.
|
|
163
|
-
|
|
164
|
-
Each file replaces a whole template. Preserve its `{{TOKENS}}`, including `{{FORMAT}}`
|
|
165
|
-
in generation wrappers, to keep the generated context and output contract. Unknown
|
|
166
|
-
generation tokens fail rendering. Chat leaves unknown tokens as written. Prompt edits
|
|
167
|
-
do not change the output schema or validation rules enforced by the tool. Overrides
|
|
168
|
-
remain yours across tool upgrades; compare them with new bundled templates when upgrading.
|
|
153
|
+
Edit the copies and configure only the templates you want to replace. Paths are relative
|
|
154
|
+
to the project root. Omitted entries use the bundled defaults. Keep each template's
|
|
155
|
+
`{{TOKENS}}`, including `{{FORMAT}}` in generation wrappers. Commit the config and
|
|
156
|
+
referenced files together.
|
|
169
157
|
|
|
170
158
|
Run `prepare` again to apply generation edits (use `--force` for an existing canvas).
|
|
171
159
|
Restart the server after changing the config; chat template edits apply to new threads.
|
|
172
160
|
|
|
161
|
+
See the [prompt template reference](docs/reference.md#prompt-templates) for supported keys,
|
|
162
|
+
path rules, validation, and upgrades.
|
|
163
|
+
|
|
173
164
|
## Contributing
|
|
174
165
|
|
|
175
166
|
In a clone of this tool, use pnpm for the shared lockfile and development checks:
|
|
@@ -177,11 +168,22 @@ In a clone of this tool, use pnpm for the shared lockfile and development checks
|
|
|
177
168
|
```bash
|
|
178
169
|
corepack pnpm --version
|
|
179
170
|
corepack pnpm install --frozen-lockfile
|
|
171
|
+
corepack pnpm hooks:install
|
|
180
172
|
corepack pnpm exec playwright install --with-deps chromium
|
|
181
173
|
corepack pnpm verify
|
|
182
174
|
corepack pnpm start --repo /path/to/your-project
|
|
183
175
|
```
|
|
184
176
|
|
|
177
|
+
The pre-commit hook runs `pnpm precommit`: lint, formatting, strict type checks, and tests.
|
|
178
|
+
Any failure blocks the commit. Run `pnpm hooks:install`
|
|
179
|
+
once per clone to enable it. Use `pnpm lint:fix` and `pnpm format` to apply automatic fixes.
|
|
180
|
+
CI runs the same checks through `pnpm verify`, with coverage executing the unit tests once.
|
|
181
|
+
|
|
182
|
+
Run the full `pnpm verify` before pushing. Keep branch coverage at least 96% when adding or
|
|
183
|
+
changing behavior, leaving a margin above CI's 95% minimum. Cover meaningful failure and boundary
|
|
184
|
+
cases rather than lowering thresholds. Each CI job uploads `coverage-node-<version>` with branch
|
|
185
|
+
locations and a summary; locally, these reports are in `coverage/` after `pnpm coverage`.
|
|
186
|
+
|
|
185
187
|
Run `pr-review --help` for CLI commands. Local data goes in the project's `.pr-review/`
|
|
186
188
|
directory; keep it out of Git.
|
|
187
189
|
|
package/docs/reference.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# CLI and configuration reference
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[README](../README.md).
|
|
5
|
-
that matters when customizing or troubleshooting a review.
|
|
3
|
+
This reference covers command options, configuration, and troubleshooting for local PR reviews.
|
|
4
|
+
For setup and the basic review workflow, see the [README](../README.md).
|
|
6
5
|
|
|
7
6
|
- [CLI options](#cli-options)
|
|
8
7
|
- [Project config](#project-config)
|
|
@@ -16,14 +15,14 @@ that matters when customizing or troubleshooting a review.
|
|
|
16
15
|
|
|
17
16
|
### Repository and runtime options
|
|
18
17
|
|
|
19
|
-
| Option
|
|
20
|
-
|
|
21
|
-
| `--repo <dir>`
|
|
22
|
-
| `--data-dir <dir>`
|
|
23
|
-
| `--port <n>`
|
|
24
|
-
| `--agent claude\|codex`
|
|
25
|
-
| `--model <id>`
|
|
26
|
-
| `--fixture-canvas <review.json>` | `serve`
|
|
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` | 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 |
|
|
27
26
|
|
|
28
27
|
Repository operations require an `origin` remote on **github.com**. GitHub Enterprise Server
|
|
29
28
|
hosts are not supported. Fetching a PR does not check out its branch.
|
|
@@ -75,6 +74,10 @@ pr-review import <zip> [--pr <n>] [--force]
|
|
|
75
74
|
the archive; it does not select the commit.
|
|
76
75
|
- `--out` defaults to the data directory's `exports/` folder. Supply an existing directory to
|
|
77
76
|
keep the generated filename, or a full `.zip` file path to choose a name.
|
|
77
|
+
- Generated names follow `pr-<number>-<YYYYMMDDTHHmmssZ>-<sha8>-<owner>-<repo>-canvas.zip`,
|
|
78
|
+
for example `pr-42-20260910T110000Z-aaaaaaaa-acme-widgets-canvas.zip`. The timestamp is the
|
|
79
|
+
canvas generation time in UTC, to seconds, so exports sort chronologically within each PR.
|
|
80
|
+
Before a PR exists, `ref-` replaces `pr-<number>-`. Re-exporting the same canvas keeps its name.
|
|
78
81
|
- Export returns `status`, `path`, `name`, `headSha`, and `prNumber` when supplied or stored.
|
|
79
82
|
- `import --pr` compares the imported canvas with that PR's current head. Without it, import does
|
|
80
83
|
not check against a live PR.
|
|
@@ -101,8 +104,19 @@ Relative custom paths resolve from the command's working directory. For example:
|
|
|
101
104
|
pr-review install-skill --codex-dir ~/.codex/skills
|
|
102
105
|
```
|
|
103
106
|
|
|
104
|
-
Installation
|
|
105
|
-
|
|
107
|
+
Installation copies the bundled skill on every platform. The copies and their `.pr-review-install`
|
|
108
|
+
marker files can be committed to Git. Re-running the command refreshes managed copies and replaces
|
|
109
|
+
legacy symlinks. An unmanaged directory requires `--force` to replace it.
|
|
110
|
+
|
|
111
|
+
Each installed `SKILL.md` records `metadata.body-sha256` in its YAML frontmatter. The SHA-256 hash
|
|
112
|
+
covers the body after the closing frontmatter delimiter, with CRLF normalized to LF. `doctor`
|
|
113
|
+
compares the recorded hash and actual body against the skill bundled with the running CLI. Any
|
|
114
|
+
outdated or modified copy in `.claude/skills` or `.agents/skills` fails the skill check, even if the
|
|
115
|
+
other copy is current. Refresh copies with `pr-review install-skill` (repeat any custom directory
|
|
116
|
+
flags used during installation). Automatic discovery checks the two default directories.
|
|
117
|
+
|
|
118
|
+
`serve` runs this skill check automatically and prints failures with a repair hint to stderr.
|
|
119
|
+
Warnings do not prevent the server from starting. Use `doctor --all-checks` for full diagnostics.
|
|
106
120
|
The `.gitignore` update always applies to the selected repository root, even with custom skill
|
|
107
121
|
directories.
|
|
108
122
|
|
|
@@ -115,13 +129,13 @@ JSON error. `serve` stays running and writes its startup message to stderr.
|
|
|
115
129
|
Command failures use `{ "error": { "code", "message", "hint" } }`, with `hint` optional.
|
|
116
130
|
Validation failures from `validate` use its report format instead.
|
|
117
131
|
|
|
118
|
-
| Exit code | Meaning
|
|
119
|
-
|
|
120
|
-
| `0`
|
|
121
|
-
| `1`
|
|
122
|
-
| `2`
|
|
123
|
-
| `4`
|
|
124
|
-
| `5`
|
|
132
|
+
| Exit code | Meaning |
|
|
133
|
+
| --------- | ------------------------------------------------------------------------ |
|
|
134
|
+
| `0` | Success |
|
|
135
|
+
| `1` | Error, including a failed `doctor` check |
|
|
136
|
+
| `2` | Command usage error, such as an unknown command or missing required flag |
|
|
137
|
+
| `4` | GitHub CLI missing or unauthenticated |
|
|
138
|
+
| `5` | Validation failed in `validate` or `publish` |
|
|
125
139
|
|
|
126
140
|
`doctor` reports failed checks with exit `1`, including authentication failures.
|
|
127
141
|
|
|
@@ -134,20 +148,20 @@ Lists you supply replace their defaults.
|
|
|
134
148
|
Path patterns match repository-relative paths. `**` crosses directories; `*` and `?` match
|
|
135
149
|
within one path segment.
|
|
136
150
|
|
|
137
|
-
| Key
|
|
138
|
-
|
|
139
|
-
| `version`
|
|
140
|
-
| `rulebook`
|
|
141
|
-
| `layers`
|
|
142
|
-
| `highRisk`
|
|
143
|
-
| `generation.mode`
|
|
144
|
-
| `generation.maxRepairRounds`
|
|
145
|
-
| `generation.inlineDiffMaxLines` | `1500`
|
|
146
|
-
| `generation.smallPrHunks`
|
|
147
|
-
| `generation.caps`
|
|
148
|
-
| `tests.patterns`
|
|
149
|
-
| `chat.enabled`
|
|
150
|
-
| `prompts`
|
|
151
|
+
| Key | Default | Details |
|
|
152
|
+
| ------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
153
|
+
| `version` | `1` | The only supported configuration version |
|
|
154
|
+
| `rulebook` | Unset | Path to a Markdown file of project code standards, resolved from the repository root; these standards take precedence over bundled standards |
|
|
155
|
+
| `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 |
|
|
156
|
+
| `highRisk` | `[]` | Entries with a `pattern` glob and `label`; matching changes receive risk labels and cannot go in the Other layer |
|
|
157
|
+
| `generation.mode` | `strict` | See [generation modes](#generation-modes) |
|
|
158
|
+
| `generation.maxRepairRounds` | `3` | Failed validation rounds allowed by the generation skill |
|
|
159
|
+
| `generation.inlineDiffMaxLines` | `1500` | Maximum diff length to include directly in the generation prompt |
|
|
160
|
+
| `generation.smallPrHunks` | `10` | At or below this hunk count, the prompt asks for one layer unless concerns differ |
|
|
161
|
+
| `generation.caps` | See below | Overrides individual text limits |
|
|
162
|
+
| `tests.patterns` | `['**/*.test.*', '**/*.spec.*', '**/__tests__/**']` | Paths treated as tests for review ordering and labels |
|
|
163
|
+
| `chat.enabled` | `true` | Set to `false` to disable AI Chat |
|
|
164
|
+
| `prompts` | Bundled templates | See [prompt templates](#prompt-templates) for supported keys and behavior |
|
|
151
165
|
|
|
152
166
|
Generation's numeric options and text caps must be positive integers. An empty `layers` list
|
|
153
167
|
provides no suggested groups; an empty `tests.patterns` list recognizes no files as tests.
|
|
@@ -164,23 +178,54 @@ not change an already prepared generation or an existing canvas.
|
|
|
164
178
|
Both modes read the project rulebook and use the same validation and review controls. The mode
|
|
165
179
|
affects canvas generation; chat answers the reviewer's selected question.
|
|
166
180
|
|
|
181
|
+
### Prompt templates
|
|
182
|
+
|
|
183
|
+
The `prompts` map in `pr-review.config.yml` accepts these keys:
|
|
184
|
+
|
|
185
|
+
| Key | Purpose |
|
|
186
|
+
| ------------------------- | ------------------------------------- |
|
|
187
|
+
| `generation-format.md` | Schema and output rules |
|
|
188
|
+
| `generation-strict.md` | Instructions for strict mode |
|
|
189
|
+
| `generation-surfacing.md` | Instructions for surfacing mode |
|
|
190
|
+
| `quality-standards.md` | Bundled code standards |
|
|
191
|
+
| `layering-guidance.md` | Guidance for grouping related changes |
|
|
192
|
+
| `chat-seed.md` | Opening AI Chat instructions |
|
|
193
|
+
|
|
194
|
+
Each configured file replaces a whole template. Paths resolve from the project root,
|
|
195
|
+
including when running from a subdirectory or using `--repo`. Absolute paths work for
|
|
196
|
+
personal templates shared across projects. Omitted entries use the installed package's
|
|
197
|
+
defaults. A configured file that cannot be read causes an error.
|
|
198
|
+
|
|
199
|
+
`generation.mode` selects the generation wrapper. The project rulebook takes precedence
|
|
200
|
+
over code standards. Configured layers and caps supply data to the templates.
|
|
201
|
+
|
|
202
|
+
Preserve `{{TOKENS}}`, including `{{FORMAT}}` in generation wrappers, so generated prompts
|
|
203
|
+
include the context and output requirements. Unknown generation tokens fail rendering;
|
|
204
|
+
chat leaves unknown tokens as written. Prompt edits do not change the output schema or
|
|
205
|
+
validation rules enforced by the tool.
|
|
206
|
+
|
|
207
|
+
Run `prepare` again to apply generation edits (use `--force` for an existing canvas).
|
|
208
|
+
Restart the server after changing the config; chat template edits apply to new threads.
|
|
209
|
+
Custom templates persist across tool upgrades. Compare them with the new bundled templates
|
|
210
|
+
when upgrading.
|
|
211
|
+
|
|
167
212
|
### Text limits
|
|
168
213
|
|
|
169
214
|
Set any of these keys under `generation.caps`. Prose limits count visible characters, so Markdown
|
|
170
215
|
link targets do not count. `diagram` counts raw Mermaid source characters.
|
|
171
216
|
|
|
172
|
-
| Key
|
|
173
|
-
|
|
174
|
-
| `summary`
|
|
175
|
-
| `layerTitle`
|
|
176
|
-
| `rationale`
|
|
177
|
-
| `decisions`
|
|
178
|
-
| `checkByHand`
|
|
179
|
-
| `annotation`
|
|
180
|
-
| `pointTitle`
|
|
181
|
-
| `pointBody`
|
|
182
|
-
| `testBehavior` | 120
|
|
183
|
-
| `diagram`
|
|
217
|
+
| Key | Default |
|
|
218
|
+
| -------------- | ------- |
|
|
219
|
+
| `summary` | 1200 |
|
|
220
|
+
| `layerTitle` | 60 |
|
|
221
|
+
| `rationale` | 300 |
|
|
222
|
+
| `decisions` | 600 |
|
|
223
|
+
| `checkByHand` | 400 |
|
|
224
|
+
| `annotation` | 240 |
|
|
225
|
+
| `pointTitle` | 90 |
|
|
226
|
+
| `pointBody` | 600 |
|
|
227
|
+
| `testBehavior` | 120 |
|
|
228
|
+
| `diagram` | 1500 |
|
|
184
229
|
|
|
185
230
|
The canvas has a separate limit of 12 attention points, including entries generated from missing
|
|
186
231
|
tests. Increasing text caps does not increase that limit.
|
|
@@ -191,7 +236,7 @@ Custom patterns replace the JavaScript/TypeScript defaults. For example, a Pytho
|
|
|
191
236
|
|
|
192
237
|
```yaml
|
|
193
238
|
tests:
|
|
194
|
-
|
|
239
|
+
patterns: ['**/test_*.py', '**/tests/**']
|
|
195
240
|
```
|
|
196
241
|
|
|
197
242
|
Test recognition controls ordering, but matching a test to its source file currently follows
|
|
@@ -200,18 +245,17 @@ placed in Other while its source is in a regular layer.
|
|
|
200
245
|
|
|
201
246
|
## Local settings and storage
|
|
202
247
|
|
|
203
|
-
|
|
204
|
-
through the UI. These are the file keys and accepted values:
|
|
248
|
+
The data directory's `settings.yml` accepts these keys and values:
|
|
205
249
|
|
|
206
|
-
| Key
|
|
207
|
-
|
|
208
|
-
| `version`
|
|
209
|
-
| `skin`
|
|
210
|
-
| `theme`
|
|
211
|
-
| `agent`
|
|
212
|
-
| `model`
|
|
213
|
-
| `chatTimeoutSec` | `600`
|
|
214
|
-
| `maxTurns`
|
|
250
|
+
| Key | Default | Accepted values |
|
|
251
|
+
| ---------------- | ---------- | ------------------------------------------------ |
|
|
252
|
+
| `version` | `1` | `1` |
|
|
253
|
+
| `skin` | `terminal` | `terminal`, `github` |
|
|
254
|
+
| `theme` | `auto` | `auto`, `light`, `dark` |
|
|
255
|
+
| `agent` | `claude` | `claude`, `codex` |
|
|
256
|
+
| `model` | `null` | A model ID, or `null` for the agent's default |
|
|
257
|
+
| `chatTimeoutSec` | `600` | Integer seconds, 30–3600 |
|
|
258
|
+
| `maxTurns` | `null` | Integer 1–100, or `null` for the agent's default |
|
|
215
259
|
|
|
216
260
|
Invalid settings fall back to defaults. URL parameters `?skin=github&theme=light` can override
|
|
217
261
|
appearance for one page load without saving it.
|
|
@@ -230,13 +274,13 @@ Deleting the directory loses saved preferences, canvases, progress, and chat his
|
|
|
230
274
|
|
|
231
275
|
Append a fragment to `/review/<pr-number>`:
|
|
232
276
|
|
|
233
|
-
| Target
|
|
234
|
-
|
|
235
|
-
| Layer
|
|
236
|
-
| File
|
|
237
|
-
| Hunk
|
|
238
|
-
| New-side line range | `#line:src/store.ts:40-52`
|
|
239
|
-
| Old-side line
|
|
277
|
+
| Target | Fragment example |
|
|
278
|
+
| ------------------- | --------------------------- |
|
|
279
|
+
| Layer | `#layer:data-access` |
|
|
280
|
+
| File | `#file:src/store.ts` |
|
|
281
|
+
| Hunk | `#hunk:src/store.ts#2` |
|
|
282
|
+
| New-side line range | `#line:src/store.ts:40-52` |
|
|
283
|
+
| Old-side line | `#line:src/store.ts:40:old` |
|
|
240
284
|
|
|
241
285
|
Use the layer key and file path from the canvas. Links open the target file when needed; if a
|
|
242
286
|
line is unavailable, navigation uses the nearest visible row. Recipients need their own running
|
|
@@ -300,41 +344,41 @@ sandbox for the agent. Its access also depends on the agent's own permissions. D
|
|
|
300
344
|
|
|
301
345
|
## Troubleshooting
|
|
302
346
|
|
|
303
|
-
| Symptom or code
|
|
304
|
-
|
|
305
|
-
| `NOT_A_REPO`
|
|
306
|
-
| `NO_ORIGIN`
|
|
307
|
-
| `GH_MISSING` / `GH_UNAUTHENTICATED`
|
|
308
|
-
| `GITHUB_API_ERROR`
|
|
309
|
-
| `PR_NOT_FOUND`
|
|
310
|
-
| `CANVAS_NOT_FOUND`
|
|
311
|
-
| `CANVAS_INVALID`
|
|
312
|
-
| `CANVAS_REPO_MISMATCH`
|
|
313
|
-
| `CANVAS_TOO_LARGE`
|
|
314
|
-
| `CANVAS_STALE`
|
|
315
|
-
| `MODEL_INVALID`
|
|
316
|
-
| `SKILL_DIR_EXISTS`
|
|
317
|
-
| `CHAT_BUSY`
|
|
318
|
-
| `AGENT_AUTH_REQUIRED`
|
|
319
|
-
| `AGENT_MISSING` or missing chat pane | Check
|
|
320
|
-
| `AGENT_INCOMPLETE`
|
|
321
|
-
| `COMMENT_FORBIDDEN`
|
|
322
|
-
| `COMMENT_LINE_NOT_IN_DIFF`
|
|
323
|
-
| `SIGNOFF_INCOMPLETE`
|
|
324
|
-
| `FORBIDDEN_HOST` / `CROSS_ORIGIN`
|
|
347
|
+
| Symptom or code | Next step |
|
|
348
|
+
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
349
|
+
| `NOT_A_REPO` | Run inside a Git clone or pass `--repo <dir>` |
|
|
350
|
+
| `NO_ORIGIN` | Check that `origin` points to a repository on github.com |
|
|
351
|
+
| `GH_MISSING` / `GH_UNAUTHENTICATED` | Install [GitHub CLI](https://cli.github.com), run `gh auth login`, and check authentication in the same environment that runs the server |
|
|
352
|
+
| `GITHUB_API_ERROR` | Read the underlying error for permissions, rate limits, connectivity, or GitHub service problems |
|
|
353
|
+
| `PR_NOT_FOUND` | Check the PR number, repository, and your access |
|
|
354
|
+
| `CANVAS_NOT_FOUND` | Generate or import a canvas for the requested commit |
|
|
355
|
+
| `CANVAS_INVALID` | Read the format errors; re-export or regenerate the canvas |
|
|
356
|
+
| `CANVAS_REPO_MISMATCH` | Check which clone is open; use `import --force` only when importing from the other repository is intentional |
|
|
357
|
+
| `CANVAS_TOO_LARGE` | The archive exceeds the 20 MiB import limit |
|
|
358
|
+
| `CANVAS_STALE` | The PR head moved; prepare again for the current commit |
|
|
359
|
+
| `MODEL_INVALID` | Fix the reported problems in `model.json`, validate, then publish again |
|
|
360
|
+
| `SKILL_DIR_EXISTS` | The destination contains a customized directory; preserve it elsewhere before replacing it with `--force` |
|
|
361
|
+
| `CHAT_BUSY` | Wait for the running reply or press **stop** |
|
|
362
|
+
| `AGENT_AUTH_REQUIRED` | Sign in through the selected agent's CLI, then retry |
|
|
363
|
+
| `AGENT_MISSING` or missing chat pane | Check `chat.enabled` and confirm the server can find `acpx` and the selected agent; run `pr-review doctor --all-checks` |
|
|
364
|
+
| `AGENT_INCOMPLETE` | Retry the message or increase the chat timeout |
|
|
365
|
+
| `COMMENT_FORBIDDEN` | Check the GitHub account's repository access and token permissions |
|
|
366
|
+
| `COMMENT_LINE_NOT_IN_DIFF` | Choose a line shown in the current diff |
|
|
367
|
+
| `SIGNOFF_INCOMPLETE` | Mark every layer except Other reviewed for this head |
|
|
368
|
+
| `FORBIDDEN_HOST` / `CROSS_ORIGIN` | Open the local server using `localhost` or `127.0.0.1` and submit actions from that page |
|
|
325
369
|
|
|
326
370
|
### Validation diagnostics
|
|
327
371
|
|
|
328
372
|
Validation reports name the field, file, hunk, or line to fix. Common groups are:
|
|
329
373
|
|
|
330
|
-
| Codes
|
|
331
|
-
|
|
332
|
-
| `SCHEMA`, `TEXT_TOO_LONG`
|
|
333
|
-
| `HUNK_UNASSIGNED`, `HUNK_DUPLICATE`, `HUNK_UNKNOWN`
|
|
334
|
-
| `PATH_UNKNOWN`, `TEST_PATH_UNKNOWN`
|
|
335
|
-
| `LAYER_EMPTY`, `LAYER_KEY_DUPLICATE`
|
|
336
|
-
| `OTHER_DUPLICATE`, `OTHER_NOT_LAST`, `RISK_IN_OTHER`
|
|
337
|
-
| `TEST_NOT_LAST`, `TEST_IN_OTHER`
|
|
338
|
-
| `ANNOTATION_OUTSIDE_HUNK`, `POINT_OUTSIDE_DIFF`, `FOLD_INVALID` | Locations and fold ranges fit the assigned diff
|
|
339
|
-
| `TOO_MANY_POINTS`
|
|
340
|
-
| `LINK_UNRESOLVED`, `DIAGRAM_NODE_UNKNOWN`, `DIAGRAM_LIMIT`
|
|
374
|
+
| Codes | What to check |
|
|
375
|
+
| --------------------------------------------------------------- | -------------------------------------------------------------- |
|
|
376
|
+
| `SCHEMA`, `TEXT_TOO_LONG` | Required fields, types, and text limits |
|
|
377
|
+
| `HUNK_UNASSIGNED`, `HUNK_DUPLICATE`, `HUNK_UNKNOWN` | Each known hunk belongs to exactly one layer |
|
|
378
|
+
| `PATH_UNKNOWN`, `TEST_PATH_UNKNOWN` | Referenced files exist in the relevant diff or PR head |
|
|
379
|
+
| `LAYER_EMPTY`, `LAYER_KEY_DUPLICATE` | Layers contain hunks and have unique keys |
|
|
380
|
+
| `OTHER_DUPLICATE`, `OTHER_NOT_LAST`, `RISK_IN_OTHER` | At most one Other layer, last, without risk-tagged changes |
|
|
381
|
+
| `TEST_NOT_LAST`, `TEST_IN_OTHER` | Tests follow the code they cover and use the appropriate layer |
|
|
382
|
+
| `ANNOTATION_OUTSIDE_HUNK`, `POINT_OUTSIDE_DIFF`, `FOLD_INVALID` | Locations and fold ranges fit the assigned diff |
|
|
383
|
+
| `TOO_MANY_POINTS` | Count explicit points and missing-test entries together |
|
|
384
|
+
| `LINK_UNRESOLVED`, `DIAGRAM_NODE_UNKNOWN`, `DIAGRAM_LIMIT` | Link targets, diagram node IDs, and diagram counts |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vintasoftware/pr-review-canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Localhost PR review canvas: layered diffs, attention points, and GitHub comments for one PR",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,13 +10,20 @@
|
|
|
10
10
|
"dev": "tsx watch --clear-screen=false --ignore '**/.pr-review/**' src/cli.ts serve",
|
|
11
11
|
"start": "tsx src/cli.ts serve",
|
|
12
12
|
"test": "vitest run",
|
|
13
|
+
"hooks:install": "git config core.hooksPath .githooks",
|
|
13
14
|
"test:watch": "vitest",
|
|
14
15
|
"test:browser": "playwright test",
|
|
15
16
|
"coverage": "vitest run --coverage",
|
|
16
17
|
"typecheck": "tsc --noEmit",
|
|
17
18
|
"test:package": "node scripts/test-package.mjs",
|
|
18
|
-
"verify": "pnpm
|
|
19
|
-
"prepublishOnly": "pnpm verify"
|
|
19
|
+
"verify": "pnpm check && pnpm coverage && pnpm test:browser --workers=2 && pnpm test:package",
|
|
20
|
+
"prepublishOnly": "pnpm verify",
|
|
21
|
+
"lint": "oxlint --deny-warnings",
|
|
22
|
+
"lint:fix": "oxlint --fix --deny-warnings",
|
|
23
|
+
"format": "oxfmt --write",
|
|
24
|
+
"format:check": "oxfmt --check",
|
|
25
|
+
"check": "pnpm lint && pnpm format:check && pnpm typecheck",
|
|
26
|
+
"precommit": "pnpm check && pnpm test"
|
|
20
27
|
},
|
|
21
28
|
"dependencies": {
|
|
22
29
|
"@highlightjs/cdn-assets": "^11.12.0",
|
|
@@ -36,6 +43,8 @@
|
|
|
36
43
|
"@types/node": "^24.13.3",
|
|
37
44
|
"@vitest/coverage-v8": "^4.1.10",
|
|
38
45
|
"happy-dom": "20.11.2",
|
|
46
|
+
"oxfmt": "^0.68.0",
|
|
47
|
+
"oxlint": "^1.83.0",
|
|
39
48
|
"typescript": "^5.9.3",
|
|
40
49
|
"vite": "~8.0.16",
|
|
41
50
|
"vitest": "^4.1.10"
|
|
@@ -11,35 +11,16 @@ version: 1
|
|
|
11
11
|
# generation-strict.md: review-prompts/generation-strict.md
|
|
12
12
|
# generation-surfacing.md: review-prompts/generation-surfacing.md
|
|
13
13
|
# quality-standards.md: review-prompts/quality-standards.md
|
|
14
|
-
#
|
|
14
|
+
# layering-guidance.md: review-prompts/layering-guidance.md
|
|
15
15
|
# chat-seed.md: review-prompts/chat-seed.md
|
|
16
16
|
|
|
17
|
-
#
|
|
18
|
-
layers:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
description: Queries, repositories, migrations, storage.
|
|
25
|
-
- id: mappers
|
|
26
|
-
title: Mappers and DTOs
|
|
27
|
-
description: Code that turns records into view models and back.
|
|
28
|
-
- id: hooks-state
|
|
29
|
-
title: Hooks and state
|
|
30
|
-
description: Hooks, query definitions, stores, state machines.
|
|
31
|
-
- id: views
|
|
32
|
-
title: Views
|
|
33
|
-
description: Components, screens, styles, copy.
|
|
34
|
-
- id: routes-wiring
|
|
35
|
-
title: Routes and wiring
|
|
36
|
-
description: Route files, providers, shells, entry points.
|
|
37
|
-
- id: policy-config
|
|
38
|
-
title: Policy and config
|
|
39
|
-
description: Access policies, environment variables, feature flags, CI, deployment, docs.
|
|
40
|
-
- id: mechanical
|
|
41
|
-
title: Mechanical changes
|
|
42
|
-
description: Renames, lockfiles, generated files, formatting, moved code.
|
|
17
|
+
# Optional layer guidance. Omit or leave empty for agent-chosen semantic sections.
|
|
18
|
+
layers: []
|
|
19
|
+
# layers:
|
|
20
|
+
# - id: checkout
|
|
21
|
+
# title: Checkout
|
|
22
|
+
# description: Cart totals, payment processing, and order creation.
|
|
23
|
+
# paths: ['src/checkout/**']
|
|
43
24
|
|
|
44
25
|
# Blast radius tags. Glob patterns against changed paths; the label shows in the header and the rail.
|
|
45
26
|
highRisk:
|
|
@@ -49,10 +30,10 @@ highRisk:
|
|
|
49
30
|
label: auth
|
|
50
31
|
|
|
51
32
|
generation:
|
|
52
|
-
mode: strict
|
|
53
|
-
maxRepairRounds: 3
|
|
33
|
+
mode: strict # strict: quality review; surfacing: walkthrough that audits as it reads
|
|
34
|
+
maxRepairRounds: 3 # publish retries the skill may make after a failed validation
|
|
54
35
|
inlineDiffMaxLines: 1500 # diffs longer than this are read per file instead of inlined in the prompt
|
|
55
|
-
smallPrHunks: 10
|
|
36
|
+
smallPrHunks: 10 # at most this many hunks: one layer unless concerns differ, fewer annotations
|
|
56
37
|
# caps: # override the text caps (characters)
|
|
57
38
|
# summary: 1800
|
|
58
39
|
# rationale: 300
|
|
@@ -65,4 +46,4 @@ tests:
|
|
|
65
46
|
patterns: ['**/*.test.*', '**/*.spec.*', '**/__tests__/**']
|
|
66
47
|
|
|
67
48
|
chat:
|
|
68
|
-
enabled: true
|
|
49
|
+
enabled: true # false removes the chat pane and its routes
|
|
@@ -39,11 +39,11 @@ hunk in that file's patch.
|
|
|
39
39
|
|
|
40
40
|
## Layering rules
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Project-configured layers (optional guidance):
|
|
43
43
|
|
|
44
|
-
{{
|
|
44
|
+
{{CONFIGURED_LAYERS}}
|
|
45
45
|
|
|
46
|
-
{{
|
|
46
|
+
{{LAYERING_GUIDANCE}}
|
|
47
47
|
|
|
48
48
|
- **Every hunk id must appear in exactly one layer.** The validator rejects an unassigned or
|
|
49
49
|
duplicated hunk. A file's hunks may be spread over several layers.
|
|
@@ -55,7 +55,7 @@ The project's default layers, in review order, are the default taxonomy:
|
|
|
55
55
|
- Test files go at the **end** of the layer whose code they cover, never in a layer of their own,
|
|
56
56
|
and into Other only together with the code they cover. This project counts a file as a test when
|
|
57
57
|
its path matches one of: {{TEST_PATTERNS}}.
|
|
58
|
-
- No empty layers. Set `defaultLayerId` when a layer derives from a
|
|
58
|
+
- No empty layers. Set `defaultLayerId` only when a layer derives from a configured layer; add, split, or reorder
|
|
59
59
|
layers when the {{TARGET_WORD}} reads better that way. Two to eight layers is typical for a
|
|
60
60
|
{{TARGET_WORD}} of any size; see the size note below for a small one.
|
|
61
61
|
- Each layer's `key` is a short lowercase slug (`auth-session`); links use it.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Choose semantic sections from the actual change: group hunks that explain one behavior, concern,
|
|
2
|
+
or decision, even when they span files or directories. Give each layer a specific title that tells
|
|
3
|
+
the reviewer what to understand.
|
|
4
|
+
|
|
5
|
+
When the project config lists layers, use their descriptions, path hints, and order as guidance.
|
|
6
|
+
Adapt, combine, split, or reorder them to fit the change. When no layers are configured, choose
|
|
7
|
+
sections yourself without assuming an architecture or a fixed list of categories.
|
|
8
|
+
|
|
9
|
+
Order sections by reviewer value. Lead with the main behavior changes, algorithms, state
|
|
10
|
+
transitions, or API changes. Follow with the integration and wiring that support them. Put
|
|
11
|
+
mechanical or low-importance hunks in Other at the end, subject to the eligibility rules below.
|
|
12
|
+
Bring a prerequisite earlier when it helps explain the main change. These priorities guide the
|
|
13
|
+
reading order; choose the number and names of sections to suit this diff.
|
|
14
|
+
|
|
15
|
+
Pair each test with its subject. A test file sits at the end of the layer whose code it covers,
|
|
16
|
+
never in a layer of its own. Match by stem: `lab-mapper.test.ts` covers `lab-mapper.ts`, and a
|
|
17
|
+
file under `__tests__/` covers the file with the same name one directory up. A test whose subject
|
|
18
|
+
is in Other may sit in Other; a test whose subject is in a real layer must sit in that layer.
|
|
@@ -39,7 +39,14 @@ pr-review prepare --base <ref> --head <ref> [--force]
|
|
|
39
39
|
Progress goes to stderr. The last stdout line is JSON:
|
|
40
40
|
|
|
41
41
|
```json
|
|
42
|
-
{
|
|
42
|
+
{
|
|
43
|
+
"canvasDir": "...",
|
|
44
|
+
"headSha": "...",
|
|
45
|
+
"mergeBaseSha": "...",
|
|
46
|
+
"promptPath": "...",
|
|
47
|
+
"contextPath": "...",
|
|
48
|
+
"status": "prepared"
|
|
49
|
+
}
|
|
43
50
|
```
|
|
44
51
|
|
|
45
52
|
- `status: "exists"` means a canvas already exists for this head. Stop and tell the user:
|