prview 0.6.0

PR Review & Artifact Generator - cross-language PR analysis tool
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
# prview usage guide

This document is the user guide for `prview`.
If you want to work on the repo, see `docs/development.md`.
If you want to understand the architecture, see `docs/architecture.md`.
For the `prview.toml` and `.prview-policy.yml` configuration files, see `docs/configuration.md`.

## Installation

### From source

```bash
cd prview-rs
cargo build --release
./target/release/prview --help
```

### Globally (cargo install)

```bash
cargo install --path .
prview --help
```

Full installation details, including release binaries and checksums, are in `docs/INSTALL.md`.

## Basic usage

### Auto mode (default)

```bash
prview
```

Automatically:
- detects the profile (JS/Rust/Python/Mixed)
- uses the current branch as the target
- diffs against the repo's default base
- in standard mode, generates the full artifact pack
- runs tests and lint by default, unless you pick a lighter mode (`--quick`, `--update`, `--ai-only`) or an explicit `--skip-*`

The `prview` tool can analyze repositories that use any base branch
(`develop`, `main`, `master`, etc.); by default it resolves the first of
`develop`, `main`, `master` that exists.

### Quick mode

```bash
prview --quick
```

Skips tests, lint, and heuristics. Diffs and core artifacts only.

`prview --quick` analyzes the current local branch (`HEAD`) and compares it
against the bases resolved for the current repo. It does not pick a PR number
automatically.

To review a specific GitHub PR:

```bash
prview --pr 23 --quick
```

### Gate mode

```bash
prview gate
prview gate --strict
prview gate --json
```

`prview gate` runs the standard fast gate profile, consumes the existing
policy/merge-gate verdict, and exits with a stable automation contract. It does
not compute a second verdict path.

| Exit code | Meaning |
|-----------|---------|
| `0` | `PASS`, or `CONDITIONAL` without `--strict` |
| `1` | `BLOCK` |
| `2` | `CONDITIONAL` with `--strict` |
| `3` | Gate execution failed before a trustworthy verdict was available |

`--json` makes stdout machine-readable (`schema_version: "gate-json/v1"`) with
the verdict, caveats, blocking issues, and artifact paths.

Local pre-push hook recipes and the recommended Shadow -> Warn -> Block rollout
are in [`docs/gate-playbook.md`](gate-playbook.md).

#### Gate profile and measured pre-push budget

`prview gate` applies its own deterministic pre-push profile. It runs as a
quick, quiet review and does not inherit global step opt-ins such as
`--with-tests`, `--with-lint`, `--with-security`, or `--security-full`.

Effective profile:

| Surface | Gate behavior |
|---------|---------------|
| Rust / Cargo | `Cargo check` runs; `Clippy`, `Rustfmt`, `Cargo test`, and `Cargo audit` stay visible as skipped checks |
| Security | Semgrep runs when the `semgrep` binary is available |
| Geiger | `Cargo geiger` is out of the gate profile |
| Tests, lint, bundle, heuristics | Disabled for the pre-push gate budget |
| JS/TS | Existing JS checks only run when repo-local `node_modules` tools exist; they are not part of the measured budget below |

Measured on 2026-07-06 with a prebuilt release binary
(`target/release/prview`); compile time is excluded.

| Repo checkout | State | Runs | Wall times | Mean | Verdicts | Dominant measured check |
|---------------|-------|------|------------|------|----------|--------------------------|
| `prview-rs` | `feat/gate-core`, W1-B worktree dirty | 2 | 8.73s, 7.36s | 8.05s | `CONDITIONAL` / exit 0 | Semgrep 4.41s; `Cargo check` cached |
| `pensieve` | `chore/deprivatize`, clean checkout, 14 commits behind origin | 2 | 48.27s, 45.95s | 47.11s | `CONDITIONAL` / exit 0 | Semgrep 32.78s |

### GitHub Actions

This repository ships a composite Action at `action.yml` for external CI usage.
It installs `prview`, runs `prview gate --json`, and maps the step result only
from the gate exit-code contract:

| Exit code | Action result |
|-----------|---------------|
| `0` | success (`PASS`, or `CONDITIONAL` without strict mode) |
| `1` | failure (`BLOCK`) |
| `2` | failure (`CONDITIONAL` with strict mode) |
| `3` | failure (gate execution error) |

Minimal blocking gate:

```yaml
permissions:
  contents: read
  security-events: write

jobs:
  prview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: vetcoders/prview-rs@main # pin to a released tag once one ships `prview gate`
        id: prview
        with:
          strict: "true"
          version: "latest"
      - uses: github/codeql-action/upload-sarif@v3
        if: ${{ steps.prview.outputs['sarif-path'] != '' }}
        with:
          sarif_file: ${{ steps.prview.outputs['sarif-path'] }}
```

Use `strict: "false"` for advisory rollout: `CONDITIONAL` remains exit `0`,
while `BLOCK` still exits `1`. Extra CLI flags can be passed as whitespace-
separated `args`.

The Action prefers `cargo-binstall` when that binary is already available on the
runner and falls back to `cargo install prview --locked --force`. Set `version`
to a published release that contains `prview gate`, or `latest` for the newest
release. The gate command is not in the `0.5.0` crate; until a release that
includes it is published, install the action from `main`.

SARIF upload requires `permissions: security-events: write`. prview writes
`30_context/INLINE_FINDINGS.sarif` only when there are inline findings or
advisories. GitHub code scanning limits matter for large diffs: SARIF uploads
must be at most 10 MB after gzip compression, and GitHub displays at most 50
annotations per workflow step.

### Specific branch and base

```bash
prview feature/my-feature main
prview feature/x main
```

## Execution modes

| Mode | What it does |
|------|--------------|
| standard (default) | Full review with tests and lint enabled by default |
| `--quick` | Light pass: skip tests/lint/bundle/heuristics |
| `--deep` | All heavier checks enabled (including security and heuristics) |
| `--ci` | Like deep, tuned for automation: no colors, strict non-zero exit |
| `--update` | Incremental rerun after new commits, skipping heavy checks unless forced |
| `--ai-only` | Minimal artifact pack for AI/review flows |

## Quick cheat sheet

```bash
# 1) Fast daily check of the current branch
prview --quick

# 2) Check a specific GitHub PR
prview --pr 23 --quick

# 3) Deeper PR analysis (tests + lint + full gate)
prview --pr 23 --deep

# 4) Compact JSON for automation (stdout = JSON only)
prview --pr 23 --quick --json --quiet

# 5) Automation gate with contractual exit codes
prview gate --json

# 6) Pick up new commits without a full run
prview --update

# 7) Fast machine-readable repo state (branch, HEAD, dirty, latest run)
prview state --json --fast
```

## zsh aliases (`prv`, `prvpr`, `prvjson`)

The repo ships a ready-to-source file:

`tools/shell/prview-aliases.zsh`

To wire it up:

```bash
echo 'source $HOME/Git/prview-rs/tools/shell/prview-aliases.zsh' >> $HOME/.zshrc
source $HOME/.zshrc
```

## Flags

This is a practical shortlist of the most common flags.
The full, always-current option list is available via:

```bash
prview --help
```

### Presets

| Flag | Effect |
|------|--------|
| `--quick` | Skip tests/lint/bundle/heuristics |
| `--deep` | Enable all checks (including security and heuristics) |
| `--ci` | CI mode: all checks, no colors, strict exit |
| `--ai-only` | Minimal checks, AI context pack only |

### Step control

| Flag | Effect |
|------|--------|
| `--with-tests` | Force tests on when a preset disabled them; also restores tests for standard `--remote-only` |
| `--skip-tests` | Skip tests |
| `--with-lint` | Force linters on when a preset disabled them; also restores heavier Rust lint for standard `--remote-only` |
| `--skip-lint` | Skip linters |
| `--with-bundle` | Enable the bundle build |
| `--skip-bundle` | Skip the bundle build |
| `--with-security` | Raise the heavy security posture (does not add cargo-geiger or full-tree Semgrep) |
| `--skip-security` | Skip heavy security checks |
| `--security-full` | Full security tier: runs full-tree Semgrep and adds cargo-geiger's unsafe scan (slow; off even under `--deep`) |

By default, Semgrep is scoped to the change when prview can resolve a clean git
baseline: it passes Semgrep `--baseline-commit <merge-base>` so existing
findings outside the diff do not degrade the merge verdict. If the worktree is
dirty or the merge-base is unavailable, prview falls back to a full scan and the
artifact classifier still separates introduced from pre-existing findings.
Semgrep parse/scan errors remain surfaced even when no rule findings are
introduced.

### Profiles

| Flag | Effect |
|------|--------|
| `--profile auto` | Auto-detect (default) |
| `--profile js` | JavaScript/TypeScript only |
| `--profile rust` | Rust only |
| `--profile python` | Python only |
| `--profile mixed` | All available |

### Special modes

| Flag | Effect |
|------|--------|
| `--update` | Incremental update (skip heavy checks) |
| `-R, --remote` | Analyze a branch from origin/ |
| `--remote-only` | Resolve bases from origin/* only; a faster remote-review preset in standard mode |
| `--local-only` | Resolve bases from local refs only |
| `--policy-file <path>` | Path to `.prview-policy.yml` |
| `--policy-mode <shadow\|warn\|block>` | Override the policy mode |
| `--why-blocked` | Explain why the merge gate is blocking |

### Output

| Flag | Effect |
|------|--------|
| `-q, --quiet` | Minimal output |
| `--json` | JSON output |
| `--no-color` | Disable ANSI colors |
| `--no-zip` | Skip ZIP creation |
| `--no-dashboard` | Skip HTML dashboard generation |

## Examples

### Rust project

```bash
prview --profile rust --with-tests feature/x main
```

### Python project

```bash
prview --profile python --with-tests --with-lint
```

### Mixed (Tauri app)

```bash
prview --profile mixed --deep
```

### CI pipeline

```bash
prview --ci feature/x main
```

### Incremental update

After new commits on a branch:

```bash
prview --update feature/x main
```

### JSON for scripts

```bash
prview --json --quiet feature/x main > summary.json
```

In `--json --quiet` mode, stdout contains only the compact JSON summary
(no banners or text summaries). This payload is meant for scripts and agents:
it carries the verdict, `output_dir`, a short `checks_summary`, `top_failures`,
`context_artifacts`, and paths to artifacts. Full detail stays in the run files
on disk, especially the canonical `RUN.json` and `MERGE_GATE.json` pair, plus
`PR_REVIEW.md`.

## Output

Artifacts are written to `$PRVIEW_HOME/runs/<repo>/<branch>/<run_id>/`
or, when `PRVIEW_HOME` is unset, to
`$HOME/.prview/runs/<repo>/<branch>/<run_id>/` in an ordered numbered layout.
New run ids use a timestamp plus short HEAD suffix, for example
`20260704-120500-a1b2c3d`; treat the full value as opaque.
A `latest` symlink points at the most recent run in
`$PRVIEW_HOME/runs/<repo>/<branch>/latest` or
`$HOME/.prview/runs/<repo>/<branch>/latest` when `PRVIEW_HOME` is unset.

```
$HOME/.prview/runs/my-repo/feature-x/20260225-185357/

├── 00_summary/
│   ├── RUN.json             # Run metadata, execution mode, check inventory
│   ├── FAILURES_SUMMARY.md  # Compact blocking failures without raw dumps
│   ├── MANIFEST.json        # SHA256 hashes for generated files
│   ├── SANITY.json          # Integrity validation results
│   ├── MERGE_GATE.json      # Machine-readable merge decision
│   ├── pr-metadata.txt      # Branch, bases, profile
│   ├── file-status.txt      # A/M/D + file paths
│   └── commit-list.txt      # hash date author message
├── 10_diff/
│   ├── full.patch            # Full diff with diff-stat header (+N -N per file)
│   ├── per-commit-diffs/     # Individual per-commit patches
│   │   ├── 00-SUMMARY.md     # Commit stats + batch mapping + thematic labels
│   │   ├── 01-abc1234-message.patch
│   │   └── ...
│   └── per-file-diffs/       # Hotspots: files with >=80 lines changed
│       ├── 00-INDEX.txt      # Index with diff-stat per file
│       └── *.patch
├── 20_quality/
│   ├── *.result.json         # Per-check machine-readable outputs
│   ├── *.log                 # Per-check raw logs
│   ├── full-checks.log       # Full output from all checks
│   ├── checks-errors.log     # Filtered: errors/warnings only, with +/-2 lines of context
│   ├── coverage-delta.txt    # Source<->test mapping with change status
│   └── BREAKING_CHANGES.md   # Removed pub symbols, changed signatures
├── 30_context/
│   ├── INLINE_FINDINGS.sarif # Optional: only when the run has findings/advisories
│   ├── changed-tests.txt     # Test files changed in this PR
│   ├── cargo-tree.txt        # (Rust) dependency tree for CVE/dependency paths
│   ├── tsc-trace.log         # (JS) optional module-resolution diagnostics
│   ├── eslint-report.json    # (JS) ESLint result
│   └── vitest-report.json    # (JS) Vitest result
├── dashboard.html            # Visual HTML summary
└── artifacts.zip             # Everything zipped
```

### Key artifacts

#### Signal generators (20_quality/, 10_diff/)

Several generators produce high-signal artifacts — each writes a file **only when**
it has something worth showing:

| Artifact | Description | When generated |
|----------|-------------|----------------|
| `checks-errors.log` | Errors and warnings from checks with +/-2 lines of context | When checks found errors |
| `BREAKING_CHANGES.md` | Removed `pub` symbols, changed signatures, new env requirements | When breaking changes are detected |
| `coverage-delta.txt` | Source-file-to-test mapping (multi-strategy matching) | When the diff contains source files |
| `per-file-diffs/` | Individual patches for files with `>=80` lines changed | When such hotspots exist |

When a generator produces no file, the CLI prints an `i` note explaining why.

#### How to read an artifact pack

- `00_summary/MERGE_GATE.json` is the canonical source of check statuses.
- `PR_REVIEW.md` is a concise review narrative, not a raw log dump.
- `00_summary/FAILURES_SUMMARY.md` summarizes blocking failures and advisories without copying whole JSON files.
- When `30_context/INLINE_FINDINGS.sarif` exists, it emits findings per location/advisory and is suitable for annotation integrations.
- In Rust runs, `PR_REVIEW.md` and `FAILURES_SUMMARY.md` can surface dependency paths to vulnerable crates based on `30_context/cargo-tree.txt`.
- `10_diff/per-commit-diffs/00-SUMMARY.md` carries both the batching and thematic batch labels.
- `20_quality/coverage-delta.txt` is a heuristic; for Rust it drops DELETED files in favor of disk searches for orphaned tests (raising an `ORPHANED_TEST_DETECTED` flag). Inline `#[cfg(test)]` modules are handled silently, without false alarms.
- In fast `remote-only` runs, heavier diagnostics such as `30_context/tsc-trace.log` or `30_context/tauri-info.log` may be intentionally skipped. Check `RUN.json` for `recommended`/`reason` notes on whether they are worth generating.

#### Commit batching

For large PRs, per-commit diffs are grouped automatically:

| Commit count | Behavior |
|--------------|----------|
| <=10 | Individual `.patch` per commit |
| 11–50 | Batches of 5 commits in `batch-NN.patch` |
| >50 | Per-commit diffs skipped (only `full.patch`) |

#### MERGE_GATE

The policy-aware merge decision. Details: `docs/contracts/merge_gate.md`.

## Troubleshooting

### "Not inside a git repository"

Run from a directory inside a git repo.

### "Could not resolve ref: &lt;branch&gt;"

The named base branch does not exist. Pass an existing branch explicitly:

```bash
prview feature/x develop
# or, if the repo has no develop:
prview feature/x main
```

### TypeScript check fails

Make sure `tsconfig.json` exists and `pnpm`/`npm` are available.

### Cargo check fails

Check that `cargo` is on PATH and `Cargo.toml` is valid.