prxref 0.2.0__tar.gz
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.
- prxref-0.2.0/.gitignore +11 -0
- prxref-0.2.0/CHANGELOG.md +106 -0
- prxref-0.2.0/CONTRIBUTING.md +101 -0
- prxref-0.2.0/LICENSE +21 -0
- prxref-0.2.0/PKG-INFO +155 -0
- prxref-0.2.0/README.md +134 -0
- prxref-0.2.0/SECURITY.md +73 -0
- prxref-0.2.0/docs/deploy.md +119 -0
- prxref-0.2.0/docs/env-vars.md +50 -0
- prxref-0.2.0/docs/forges.md +71 -0
- prxref-0.2.0/docs/llm.md +61 -0
- prxref-0.2.0/examples/bitbucket-pipelines.yml +32 -0
- prxref-0.2.0/examples/github-actions-inline.yml +47 -0
- prxref-0.2.0/examples/gitlab-ci.yml +28 -0
- prxref-0.2.0/pyproject.toml +72 -0
- prxref-0.2.0/src/prxref/__init__.py +3 -0
- prxref-0.2.0/src/prxref/cli.py +214 -0
- prxref-0.2.0/src/prxref/config.py +147 -0
- prxref-0.2.0/src/prxref/forges/__init__.py +0 -0
- prxref-0.2.0/src/prxref/forges/base.py +101 -0
- prxref-0.2.0/src/prxref/forges/bitbucket.py +265 -0
- prxref-0.2.0/src/prxref/forges/github.py +190 -0
- prxref-0.2.0/src/prxref/forges/gitlab.py +369 -0
- prxref-0.2.0/src/prxref/formatter.py +197 -0
- prxref-0.2.0/src/prxref/llm.py +41 -0
- prxref-0.2.0/src/prxref/llm_backends.py +242 -0
- prxref-0.2.0/src/prxref/orchestrator.py +406 -0
- prxref-0.2.0/src/prxref/parser.py +110 -0
- prxref-0.2.0/src/prxref/prompts/.gitkeep +0 -0
- prxref-0.2.0/src/prxref/prompts/summary.md +11 -0
- prxref-0.2.0/src/prxref/prompts/worker.md +62 -0
- prxref-0.2.0/src/prxref/quality.py +265 -0
- prxref-0.2.0/src/prxref/reviewer.py +183 -0
- prxref-0.2.0/src/prxref/triage.py +367 -0
- prxref-0.2.0/src/prxref/webhooks.py +261 -0
- prxref-0.2.0/tests/__init__.py +0 -0
- prxref-0.2.0/tests/test_cli.py +294 -0
- prxref-0.2.0/tests/test_config.py +207 -0
- prxref-0.2.0/tests/test_forge_gitlab.py +362 -0
- prxref-0.2.0/tests/test_formatter.py +204 -0
- prxref-0.2.0/tests/test_integration.py +616 -0
- prxref-0.2.0/tests/test_llm_backends.py +334 -0
- prxref-0.2.0/tests/test_orchestrator.py +474 -0
- prxref-0.2.0/tests/test_parser.py +84 -0
- prxref-0.2.0/tests/test_quality.py +255 -0
- prxref-0.2.0/tests/test_reviewer.py +246 -0
- prxref-0.2.0/tests/test_triage.py +280 -0
- prxref-0.2.0/tests/test_webhooks.py +470 -0
prxref-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
6
|
+
this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] — 2026-08-26
|
|
11
|
+
|
|
12
|
+
First published release. 0.1.0 was never tagged or uploaded — its entry is kept
|
|
13
|
+
below as the development baseline for the work it describes.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **Shipped defaults no longer point at anything.** `PRXREF_LLM_BASE_URL`,
|
|
18
|
+
`PRXREF_LLM_API_KEY` and `PRXREF_LLM_MODELS` now default to empty. They
|
|
19
|
+
previously defaulted to a private LAN endpoint (`http://127.0.0.1:8090/v1`,
|
|
20
|
+
model chain `flash,orch`), so a fresh install with no configuration issued a
|
|
21
|
+
request that could only fail, against infrastructure that was never yours.
|
|
22
|
+
- **`prxref review` exits 2 when required configuration is missing**, raising
|
|
23
|
+
the new `prxref.llm.ConfigError` naming the exact variable to set. This is
|
|
24
|
+
narrow and deliberate: a missing endpoint is a usage error, not a review
|
|
25
|
+
outcome. Genuine review failures still exit 0 — non-blocking is a product
|
|
26
|
+
tenet and is unchanged. An empty `PRXREF_LLM_API_KEY` remains valid, since a
|
|
27
|
+
local no-auth server (Ollama, vLLM) needs none.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- **`PRXREF_ALLOW_UNSIGNED` was parsed two different ways.** `config.py`
|
|
32
|
+
accepted `1`, `true`, `yes` and `on`, while `webhooks._allow_unsigned` — the
|
|
33
|
+
only gate that runs — accepted the literal `1` alone, and nothing in the
|
|
34
|
+
package read the config value at all. Setting it to `true` made the config
|
|
35
|
+
dict report the bypass as enabled while signature verification stayed on.
|
|
36
|
+
This failed safe, so it was a correctness and documentation defect rather
|
|
37
|
+
than a hole. Both now parse identically, pinned by a test asserting they
|
|
38
|
+
agree across 15 inputs.
|
|
39
|
+
- **The bundled `pull_request_target` review workflow could never install
|
|
40
|
+
prxref.** It used `uv pip install --system`, which fails on GitHub's Ubuntu
|
|
41
|
+
runners because their system interpreter is PEP 668 externally-managed, and
|
|
42
|
+
which additionally suppressed the virtualenv the setup action provisions.
|
|
43
|
+
The failure was invisible: `continue-on-error` masked it and the review step
|
|
44
|
+
was skipped rather than failed, so the run reported success without a review
|
|
45
|
+
having happened.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- A test pinning the packaging metadata version to `prxref.__version__`, so the
|
|
50
|
+
two version declarations cannot drift apart across a release.
|
|
51
|
+
|
|
52
|
+
## [0.1.0] — 2026-08-26
|
|
53
|
+
|
|
54
|
+
Development baseline. Never published to PyPI and never tagged; superseded by
|
|
55
|
+
0.2.0 before release.
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **Three forges behind one command.** `prxref review --pr-url <url>` detects
|
|
60
|
+
Bitbucket Cloud, GitHub, GitHub Enterprise Server, GitLab SaaS, and self-hosted
|
|
61
|
+
GitLab from the URL alone, including arbitrarily nested GitLab subgroups. All
|
|
62
|
+
three adapters implement a single `Forge` Protocol.
|
|
63
|
+
- **Review pipeline.** Parses one unified diff, partitions it into risk-ranked
|
|
64
|
+
chunks, fans out parallel single-shot LLM worker reviews, then gates findings
|
|
65
|
+
through deterministic quality passes (line alignment, dedup, confidence floor)
|
|
66
|
+
before posting.
|
|
67
|
+
- **Provider-agnostic LLM access with a fallback chain.** `PRXREF_LLM_MODELS`
|
|
68
|
+
is tried left to right; a model that times out, refuses, or returns malformed
|
|
69
|
+
JSON is abandoned immediately for the next one, with no same-model retries.
|
|
70
|
+
Backends: plain-HTTP OpenAI-compatible (default, zero extra dependencies),
|
|
71
|
+
`litellm` (optional extra). prxref reads no upstream provider credentials.
|
|
72
|
+
- **Inline comments plus a summary.** On GitHub and GitLab, summaries are
|
|
73
|
+
deduplicated across re-runs via a hidden `<!-- prxref-summary -->` marker — a
|
|
74
|
+
re-review updates the existing comment instead of stacking a new one.
|
|
75
|
+
Bitbucket posts a fresh summary each run. Every comment carries model
|
|
76
|
+
attribution.
|
|
77
|
+
- **Webhook server.** `prxref serve` verifies HMAC-SHA256 (GitHub, Bitbucket) or
|
|
78
|
+
a shared token (GitLab) in constant time, returns `202 Accepted` immediately,
|
|
79
|
+
and processes reviews serially on one background worker. `GET /health` for
|
|
80
|
+
liveness.
|
|
81
|
+
- **Graceful degradation per forge.** GitHub 422s on out-of-hunk lines are
|
|
82
|
+
skipped; GitLab position-anchoring failures fall back to a plain note;
|
|
83
|
+
Bitbucket inline 4xxs are non-fatal.
|
|
84
|
+
- Docker image and compose file, systemd unit example, and CI templates for
|
|
85
|
+
GitHub Actions, GitLab CI, and Bitbucket Pipelines.
|
|
86
|
+
- Docs: [deployment](docs/deploy.md), [forge specifics](docs/forges.md),
|
|
87
|
+
[LLM backends](docs/llm.md), [environment variables](docs/env-vars.md).
|
|
88
|
+
|
|
89
|
+
### Security
|
|
90
|
+
|
|
91
|
+
- `PRXREF_ALLOW_UNSIGNED` requires the literal string `1`. `true`, `yes`, and
|
|
92
|
+
`on` are deliberately rejected so a stray truthy value cannot silently disable
|
|
93
|
+
webhook signature verification. Even when enabled, a payload carrying a wrong
|
|
94
|
+
signature is still rejected — only a missing one is tolerated.
|
|
95
|
+
- Per-forge token separation, so a self-hosted GitHub Enterprise token is never
|
|
96
|
+
sent to `github.com`.
|
|
97
|
+
|
|
98
|
+
### Notes
|
|
99
|
+
|
|
100
|
+
- `review` exits 0 even when the review fails. prxref is an advisor, not a merge
|
|
101
|
+
gate; do not build a security control on its exit code.
|
|
102
|
+
- Diff content is sent to whichever OpenAI-compatible endpoint you configure.
|
|
103
|
+
- Requires Python 3.12+. Tested on 3.12 and 3.13.
|
|
104
|
+
|
|
105
|
+
[Unreleased]: https://github.com/sblattj/prxref/compare/v0.2.0...HEAD
|
|
106
|
+
[0.2.0]: https://github.com/sblattj/prxref/releases/tag/v0.2.0
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Contributing to prxref
|
|
2
|
+
|
|
3
|
+
Thanks for taking the time. Bug reports, forge quirks, and prompt improvements
|
|
4
|
+
are all welcome.
|
|
5
|
+
|
|
6
|
+
## Development Setup
|
|
7
|
+
|
|
8
|
+
prxref uses [uv](https://docs.astral.sh/uv/) for environments and locking.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
git clone https://github.com/sblattj/prxref
|
|
12
|
+
cd prxref
|
|
13
|
+
uv sync --extra dev
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## The Checks
|
|
17
|
+
|
|
18
|
+
Both must pass before a PR can merge. CI runs exactly these on Python 3.12 and
|
|
19
|
+
3.13:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uv run pytest # 236 tests, no network required
|
|
23
|
+
uv run ruff check src tests
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The suite is fully offline — every forge and LLM call is stubbed. If a change
|
|
27
|
+
you make needs the network to test, that is a design smell worth raising in the
|
|
28
|
+
issue first.
|
|
29
|
+
|
|
30
|
+
To check that packaging still works:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv build # must produce BOTH a .tar.gz and a .whl
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Architecture
|
|
37
|
+
|
|
38
|
+
One unified diff in, inline comments out:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
PR URL -> detect_forge -> Forge adapter -> unified diff -> risk-ranked chunks
|
|
42
|
+
-> parallel LLM workers (fallback chain) -> quality gate -> post
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- `forges/base.py` defines a single `Forge` Protocol. `bitbucket.py`,
|
|
46
|
+
`github.py`, and `gitlab.py` implement it. **Adding a forge means implementing
|
|
47
|
+
that Protocol and nothing else** — the pipeline above is forge-agnostic.
|
|
48
|
+
- `llm_backends.py` holds the interchangeable backends. Core code talks to the
|
|
49
|
+
protocol in `llm.py`, never to a vendor SDK.
|
|
50
|
+
- `quality.py` is deterministic. Findings are dropped by rule, not by asking a
|
|
51
|
+
model to double-check.
|
|
52
|
+
|
|
53
|
+
## Conventions
|
|
54
|
+
|
|
55
|
+
These are load-bearing, not style preferences:
|
|
56
|
+
|
|
57
|
+
- **stdlib + `requests` only in core.** Every LLM backend beyond the plain-HTTP
|
|
58
|
+
one is an optional extra. A core import of a heavy dependency is a bug.
|
|
59
|
+
- **No provider credentials.** prxref reads no OpenAI/AWS/Google/Anthropic key.
|
|
60
|
+
It calls one OpenAI-compatible endpoint the user configures. Keep it that way.
|
|
61
|
+
- **Single-shot LLM calls only.** All context is gathered before the call. No
|
|
62
|
+
agent loops, no tool use, no multi-turn negotiation with the model.
|
|
63
|
+
- **Non-blocking by design.** `review` exits 0 even when the review fails.
|
|
64
|
+
prxref advises; it does not gate merges. Do not add a failure exit code.
|
|
65
|
+
- **Every posted comment carries model attribution.**
|
|
66
|
+
- Docstrings on public API. No inline commentary restating the code.
|
|
67
|
+
|
|
68
|
+
## Prompt Changes
|
|
69
|
+
|
|
70
|
+
`src/prxref/prompts/*.md` are packaged data files loaded via
|
|
71
|
+
`importlib.resources`. If you add one, confirm it survives packaging:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv build && python -c "
|
|
75
|
+
import zipfile, glob
|
|
76
|
+
print([n for n in zipfile.ZipFile(glob.glob('dist/*.whl')[0]).namelist() if 'prompts' in n])"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Prompt edits change review output in ways tests cannot fully capture. Say in the
|
|
80
|
+
PR what you ran it against and what changed in the findings.
|
|
81
|
+
|
|
82
|
+
## Pull Requests
|
|
83
|
+
|
|
84
|
+
- Branch off `main`, one logical change per PR.
|
|
85
|
+
- Say what breaks without the change, not just what the change does.
|
|
86
|
+
- New behavior needs a test. Bug fixes need a test that fails before the fix.
|
|
87
|
+
- prxref reviews its own PRs — it is an advisor, so feel free to disagree with it
|
|
88
|
+
in a comment.
|
|
89
|
+
|
|
90
|
+
## Reporting Bugs
|
|
91
|
+
|
|
92
|
+
Include the forge, the URL shape that failed (redacted is fine), the backend and
|
|
93
|
+
model chain, and the output of `prxref review --pr-url ... -v`. Forge API quirks
|
|
94
|
+
are the most common cause, and the verbose output usually shows which call
|
|
95
|
+
returned what.
|
|
96
|
+
|
|
97
|
+
For security issues, do **not** open an issue — see [SECURITY.md](SECURITY.md).
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
Contributions are licensed under the MIT License, matching the project.
|
prxref-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stephen Blatt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
prxref-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: prxref
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Fast automated AI code review for Bitbucket, GitLab, and GitHub
|
|
5
|
+
Project-URL: Homepage, https://github.com/sblattj/prxref
|
|
6
|
+
Project-URL: Repository, https://github.com/sblattj/prxref
|
|
7
|
+
Project-URL: Issues, https://github.com/sblattj/prxref/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/sblattj/prxref/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Stephen Blatt
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Python: >=3.12
|
|
13
|
+
Requires-Dist: requests>=2.31
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
18
|
+
Provides-Extra: litellm
|
|
19
|
+
Requires-Dist: litellm>=1.40; extra == 'litellm'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# prxref
|
|
23
|
+
|
|
24
|
+
Fast automated AI code review for Bitbucket, GitLab, and GitHub.
|
|
25
|
+
|
|
26
|
+
prxref inspects pull and merge requests across the three major code hosting forges in sub-minute review cycles. It parses unified diffs, partitions changes into risk-ranked chunks, fans out parallel single-shot LLM reviews across a cheap-first model fallback chain, filters findings through deterministic quality gates, and publishes inline comments alongside an executive summary.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
┌──────────────────────┐
|
|
30
|
+
│ Pull / MR URL │
|
|
31
|
+
└──────────┬───────────┘
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌──────────────────────┐
|
|
35
|
+
│ detect_forge │
|
|
36
|
+
└──────────┬───────────┘
|
|
37
|
+
│
|
|
38
|
+
▼
|
|
39
|
+
┌──────────────────────┐
|
|
40
|
+
│ Forge Adapter │
|
|
41
|
+
│ (BB / GitHub / GL) │
|
|
42
|
+
└──────────┬───────────┘
|
|
43
|
+
│
|
|
44
|
+
▼
|
|
45
|
+
┌──────────────────────┐
|
|
46
|
+
│ Unified Diff │
|
|
47
|
+
└──────────┬───────────┘
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
50
|
+
┌──────────────────────┐
|
|
51
|
+
│ Risk-Ranked Chunking │
|
|
52
|
+
└──────────┬───────────┘
|
|
53
|
+
│
|
|
54
|
+
▼
|
|
55
|
+
┌──────────────────────┐
|
|
56
|
+
│ Parallel LLM Workers │
|
|
57
|
+
│ (Fallback Chain) │
|
|
58
|
+
└──────────┬───────────┘
|
|
59
|
+
│
|
|
60
|
+
▼
|
|
61
|
+
┌──────────────────────┐
|
|
62
|
+
│ Quality Gate │
|
|
63
|
+
│ Line Align / Dedup │
|
|
64
|
+
└──────────┬───────────┘
|
|
65
|
+
│
|
|
66
|
+
▼
|
|
67
|
+
┌──────────────────────┐
|
|
68
|
+
│ Post Inline Comments │
|
|
69
|
+
│ + Summary │
|
|
70
|
+
└──────────────────────┘
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Quickstart
|
|
74
|
+
|
|
75
|
+
Run reviews instantly without local installation using `uvx`, or install the CLI globally:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Run one-shot review via uvx
|
|
79
|
+
uvx prxref review --pr-url https://github.com/org/repo/pull/123
|
|
80
|
+
|
|
81
|
+
# Or install tool globally
|
|
82
|
+
uv tool install prxref
|
|
83
|
+
prxref review --pr-url https://github.com/org/repo/pull/123
|
|
84
|
+
|
|
85
|
+
# Or install straight from source (works before the first PyPI release)
|
|
86
|
+
uv tool install git+https://github.com/sblattj/prxref
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Review Any Forge
|
|
90
|
+
|
|
91
|
+
Pass any PR or MR URL directly. Forge type, repository namespace, and pull request ID are detected automatically:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Bitbucket Cloud
|
|
95
|
+
prxref review --pr-url https://bitbucket.org/workspace/repo/pull-requests/42
|
|
96
|
+
|
|
97
|
+
# GitHub & GitHub Enterprise
|
|
98
|
+
prxref review --pr-url https://github.com/owner/repository/pull/108
|
|
99
|
+
|
|
100
|
+
# GitLab & Self-Hosted GitLab (including nested subgroups)
|
|
101
|
+
prxref review --pr-url https://gitlab.com/group/subgroup/project/-/merge_requests/15
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## LLM Configuration
|
|
105
|
+
|
|
106
|
+
prxref operates without direct cloud provider SDK keys (no Anthropic API keys). It ships with **no default endpoint and no default model chain**: point it at any OpenAI-compatible `/chat/completions` server (OpenRouter, Together, Groq, vLLM, Ollama, a self-hosted gateway), or install the optional `litellm` extra. `PRXREF_LLM_BASE_URL` and `PRXREF_LLM_MODELS` are required — leaving either unset exits `2` with an error naming the variable.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Default backend: plain HTTP to any OpenAI-compatible endpoint
|
|
110
|
+
export PRXREF_LLM_BACKEND=http
|
|
111
|
+
export PRXREF_LLM_BASE_URL="https://openrouter.ai/api/v1"
|
|
112
|
+
export PRXREF_LLM_API_KEY="$OPENROUTER_API_KEY"
|
|
113
|
+
export PRXREF_LLM_MODELS="z-ai/glm-5.3-flash"
|
|
114
|
+
export PRXREF_LLM_REASONING_EFFORT=low
|
|
115
|
+
|
|
116
|
+
# Optional: in-process litellm extra
|
|
117
|
+
# pip install 'prxref[litellm]'
|
|
118
|
+
export PRXREF_LLM_BACKEND=litellm
|
|
119
|
+
export PRXREF_LLM_MODELS="openrouter/meta-llama/llama-3.3-70b-instruct,bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
See [docs/llm.md](docs/llm.md) for architecture, failover behavior, and backend setup.
|
|
123
|
+
|
|
124
|
+
## Forge Authentication
|
|
125
|
+
|
|
126
|
+
Configure the authentication token matching your forge:
|
|
127
|
+
|
|
128
|
+
| Forge | Environment Variable | Notes |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| **Bitbucket** | `PRXREF_BITBUCKET_TOKEN` | Bearer token (workspace or repo access token) |
|
|
131
|
+
| **Bitbucket (Basic)** | `PRXREF_BITBUCKET_USER` + `PRXREF_BITBUCKET_APP_PASSWORD` | App password fallback |
|
|
132
|
+
| **GitHub** | `PRXREF_GITHUB_TOKEN` | Personal Access Token (PAT) or GitHub App token |
|
|
133
|
+
| **GitHub Enterprise** | `PRXREF_GITHUB_ENTERPRISE_TOKEN` | Used when host is not `github.com` (falls back to `PRXREF_GITHUB_TOKEN`) |
|
|
134
|
+
| **GitLab** | `PRXREF_GITLAB_TOKEN` | Personal, project, or group access token (`PRIVATE-TOKEN`) |
|
|
135
|
+
|
|
136
|
+
See [docs/env-vars.md](docs/env-vars.md) for the full configuration reference and [docs/forges.md](docs/forges.md) for forge specifics.
|
|
137
|
+
|
|
138
|
+
## Webhook Server
|
|
139
|
+
|
|
140
|
+
Run prxref as a persistent daemon to handle webhook events from GitHub, Bitbucket, and GitLab:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
prxref serve --port 8080 --host 0.0.0.0
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The service exposes:
|
|
147
|
+
- `POST /webhook` — verifies HMAC or token signatures per forge, enqueues incoming PR events, and responds immediately with `202 Accepted`. A background worker processes reviews serially.
|
|
148
|
+
- `GET /health` — liveness probe returning `{"ok": true}`.
|
|
149
|
+
|
|
150
|
+
## CLI Flags
|
|
151
|
+
|
|
152
|
+
- `--pr-url URL` — full web URL of the PR or MR (required for `review`).
|
|
153
|
+
- `--no-post` — dry run; run review analysis and quality passes without writing comments to the forge.
|
|
154
|
+
- `--max-chunks N` — override maximum diff chunks evaluated (default `8`).
|
|
155
|
+
- `-v, --verbose` — output run timing, token counts, and finding breakdowns to stdout.
|
prxref-0.2.0/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# prxref
|
|
2
|
+
|
|
3
|
+
Fast automated AI code review for Bitbucket, GitLab, and GitHub.
|
|
4
|
+
|
|
5
|
+
prxref inspects pull and merge requests across the three major code hosting forges in sub-minute review cycles. It parses unified diffs, partitions changes into risk-ranked chunks, fans out parallel single-shot LLM reviews across a cheap-first model fallback chain, filters findings through deterministic quality gates, and publishes inline comments alongside an executive summary.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
┌──────────────────────┐
|
|
9
|
+
│ Pull / MR URL │
|
|
10
|
+
└──────────┬───────────┘
|
|
11
|
+
│
|
|
12
|
+
▼
|
|
13
|
+
┌──────────────────────┐
|
|
14
|
+
│ detect_forge │
|
|
15
|
+
└──────────┬───────────┘
|
|
16
|
+
│
|
|
17
|
+
▼
|
|
18
|
+
┌──────────────────────┐
|
|
19
|
+
│ Forge Adapter │
|
|
20
|
+
│ (BB / GitHub / GL) │
|
|
21
|
+
└──────────┬───────────┘
|
|
22
|
+
│
|
|
23
|
+
▼
|
|
24
|
+
┌──────────────────────┐
|
|
25
|
+
│ Unified Diff │
|
|
26
|
+
└──────────┬───────────┘
|
|
27
|
+
│
|
|
28
|
+
▼
|
|
29
|
+
┌──────────────────────┐
|
|
30
|
+
│ Risk-Ranked Chunking │
|
|
31
|
+
└──────────┬───────────┘
|
|
32
|
+
│
|
|
33
|
+
▼
|
|
34
|
+
┌──────────────────────┐
|
|
35
|
+
│ Parallel LLM Workers │
|
|
36
|
+
│ (Fallback Chain) │
|
|
37
|
+
└──────────┬───────────┘
|
|
38
|
+
│
|
|
39
|
+
▼
|
|
40
|
+
┌──────────────────────┐
|
|
41
|
+
│ Quality Gate │
|
|
42
|
+
│ Line Align / Dedup │
|
|
43
|
+
└──────────┬───────────┘
|
|
44
|
+
│
|
|
45
|
+
▼
|
|
46
|
+
┌──────────────────────┐
|
|
47
|
+
│ Post Inline Comments │
|
|
48
|
+
│ + Summary │
|
|
49
|
+
└──────────────────────┘
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Quickstart
|
|
53
|
+
|
|
54
|
+
Run reviews instantly without local installation using `uvx`, or install the CLI globally:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Run one-shot review via uvx
|
|
58
|
+
uvx prxref review --pr-url https://github.com/org/repo/pull/123
|
|
59
|
+
|
|
60
|
+
# Or install tool globally
|
|
61
|
+
uv tool install prxref
|
|
62
|
+
prxref review --pr-url https://github.com/org/repo/pull/123
|
|
63
|
+
|
|
64
|
+
# Or install straight from source (works before the first PyPI release)
|
|
65
|
+
uv tool install git+https://github.com/sblattj/prxref
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Review Any Forge
|
|
69
|
+
|
|
70
|
+
Pass any PR or MR URL directly. Forge type, repository namespace, and pull request ID are detected automatically:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Bitbucket Cloud
|
|
74
|
+
prxref review --pr-url https://bitbucket.org/workspace/repo/pull-requests/42
|
|
75
|
+
|
|
76
|
+
# GitHub & GitHub Enterprise
|
|
77
|
+
prxref review --pr-url https://github.com/owner/repository/pull/108
|
|
78
|
+
|
|
79
|
+
# GitLab & Self-Hosted GitLab (including nested subgroups)
|
|
80
|
+
prxref review --pr-url https://gitlab.com/group/subgroup/project/-/merge_requests/15
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## LLM Configuration
|
|
84
|
+
|
|
85
|
+
prxref operates without direct cloud provider SDK keys (no Anthropic API keys). It ships with **no default endpoint and no default model chain**: point it at any OpenAI-compatible `/chat/completions` server (OpenRouter, Together, Groq, vLLM, Ollama, a self-hosted gateway), or install the optional `litellm` extra. `PRXREF_LLM_BASE_URL` and `PRXREF_LLM_MODELS` are required — leaving either unset exits `2` with an error naming the variable.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Default backend: plain HTTP to any OpenAI-compatible endpoint
|
|
89
|
+
export PRXREF_LLM_BACKEND=http
|
|
90
|
+
export PRXREF_LLM_BASE_URL="https://openrouter.ai/api/v1"
|
|
91
|
+
export PRXREF_LLM_API_KEY="$OPENROUTER_API_KEY"
|
|
92
|
+
export PRXREF_LLM_MODELS="z-ai/glm-5.3-flash"
|
|
93
|
+
export PRXREF_LLM_REASONING_EFFORT=low
|
|
94
|
+
|
|
95
|
+
# Optional: in-process litellm extra
|
|
96
|
+
# pip install 'prxref[litellm]'
|
|
97
|
+
export PRXREF_LLM_BACKEND=litellm
|
|
98
|
+
export PRXREF_LLM_MODELS="openrouter/meta-llama/llama-3.3-70b-instruct,bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0"
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
See [docs/llm.md](docs/llm.md) for architecture, failover behavior, and backend setup.
|
|
102
|
+
|
|
103
|
+
## Forge Authentication
|
|
104
|
+
|
|
105
|
+
Configure the authentication token matching your forge:
|
|
106
|
+
|
|
107
|
+
| Forge | Environment Variable | Notes |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| **Bitbucket** | `PRXREF_BITBUCKET_TOKEN` | Bearer token (workspace or repo access token) |
|
|
110
|
+
| **Bitbucket (Basic)** | `PRXREF_BITBUCKET_USER` + `PRXREF_BITBUCKET_APP_PASSWORD` | App password fallback |
|
|
111
|
+
| **GitHub** | `PRXREF_GITHUB_TOKEN` | Personal Access Token (PAT) or GitHub App token |
|
|
112
|
+
| **GitHub Enterprise** | `PRXREF_GITHUB_ENTERPRISE_TOKEN` | Used when host is not `github.com` (falls back to `PRXREF_GITHUB_TOKEN`) |
|
|
113
|
+
| **GitLab** | `PRXREF_GITLAB_TOKEN` | Personal, project, or group access token (`PRIVATE-TOKEN`) |
|
|
114
|
+
|
|
115
|
+
See [docs/env-vars.md](docs/env-vars.md) for the full configuration reference and [docs/forges.md](docs/forges.md) for forge specifics.
|
|
116
|
+
|
|
117
|
+
## Webhook Server
|
|
118
|
+
|
|
119
|
+
Run prxref as a persistent daemon to handle webhook events from GitHub, Bitbucket, and GitLab:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
prxref serve --port 8080 --host 0.0.0.0
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The service exposes:
|
|
126
|
+
- `POST /webhook` — verifies HMAC or token signatures per forge, enqueues incoming PR events, and responds immediately with `202 Accepted`. A background worker processes reviews serially.
|
|
127
|
+
- `GET /health` — liveness probe returning `{"ok": true}`.
|
|
128
|
+
|
|
129
|
+
## CLI Flags
|
|
130
|
+
|
|
131
|
+
- `--pr-url URL` — full web URL of the PR or MR (required for `review`).
|
|
132
|
+
- `--no-post` — dry run; run review analysis and quality passes without writing comments to the forge.
|
|
133
|
+
- `--max-chunks N` — override maximum diff chunks evaluated (default `8`).
|
|
134
|
+
- `-v, --verbose` — output run timing, token counts, and finding breakdowns to stdout.
|
prxref-0.2.0/SECURITY.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
Please report security issues privately through GitHub's
|
|
6
|
+
[private vulnerability reporting](https://github.com/sblattj/prxref/security/advisories/new)
|
|
7
|
+
rather than opening a public issue.
|
|
8
|
+
|
|
9
|
+
Include the version, the forge and backend involved, and the smallest set of
|
|
10
|
+
steps that reproduces the problem. You should get an initial response within a
|
|
11
|
+
week.
|
|
12
|
+
|
|
13
|
+
## Supported Versions
|
|
14
|
+
|
|
15
|
+
prxref is pre-1.0. Only the latest release receives security fixes.
|
|
16
|
+
|
|
17
|
+
## Security Model
|
|
18
|
+
|
|
19
|
+
prxref holds credentials for third-party code forges and accepts unauthenticated
|
|
20
|
+
network input on its webhook endpoint. The properties below are the ones worth
|
|
21
|
+
attacking, and the ones worth reporting if you can break them.
|
|
22
|
+
|
|
23
|
+
### Credentials
|
|
24
|
+
|
|
25
|
+
- Every credential is read from the environment at call time. prxref writes no
|
|
26
|
+
credential file and has no config file that can hold one.
|
|
27
|
+
- prxref reads **no upstream LLM provider credentials** — no OpenAI, AWS, Google,
|
|
28
|
+
or Anthropic keys. It talks to one OpenAI-compatible endpoint whose URL and key
|
|
29
|
+
you supply. Provider credentials live behind that endpoint, not here.
|
|
30
|
+
- Forge tokens are scoped per forge (`PRXREF_BITBUCKET_TOKEN`,
|
|
31
|
+
`PRXREF_GITHUB_TOKEN`, `PRXREF_GITHUB_ENTERPRISE_TOKEN`, `PRXREF_GITLAB_TOKEN`).
|
|
32
|
+
Grant only pull-request write scope.
|
|
33
|
+
- `PRXREF_GITHUB_ENTERPRISE_TOKEN` exists so a self-hosted GHES token is not sent
|
|
34
|
+
to `github.com`. Host determines which token is used.
|
|
35
|
+
|
|
36
|
+
See [docs/env-vars.md](docs/env-vars.md) for the full variable table.
|
|
37
|
+
|
|
38
|
+
### Webhook signature verification
|
|
39
|
+
|
|
40
|
+
`prxref serve` verifies every payload before acting on it:
|
|
41
|
+
|
|
42
|
+
| Forge | Header | Scheme |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| GitHub | `X-Hub-Signature-256` | HMAC-SHA256, constant-time compare |
|
|
45
|
+
| Bitbucket | `X-Hub-Signature` | HMAC-SHA256, constant-time compare |
|
|
46
|
+
| GitLab | `X-Gitlab-Token` | shared secret, constant-time compare |
|
|
47
|
+
|
|
48
|
+
A payload that fails verification is rejected and never reaches the review
|
|
49
|
+
pipeline. A correctly-signed payload for an event prxref does not handle is
|
|
50
|
+
ignored rather than queued.
|
|
51
|
+
|
|
52
|
+
### `PRXREF_ALLOW_UNSIGNED`
|
|
53
|
+
|
|
54
|
+
This flag disables signature verification and is for local development only.
|
|
55
|
+
**Do not set it in production.**
|
|
56
|
+
|
|
57
|
+
It requires the **literal string `1`**. `true`, `yes`, and `on` are deliberately
|
|
58
|
+
rejected so that a stray truthy value cannot silently disable verification. When
|
|
59
|
+
it is on, prxref logs a warning at startup and marks each bypassed response with
|
|
60
|
+
an `X-Prxref-Warning` header.
|
|
61
|
+
|
|
62
|
+
Even with the bypass on, a payload carrying a *wrong* signature is still
|
|
63
|
+
rejected — the bypass only tolerates a *missing* one.
|
|
64
|
+
|
|
65
|
+
### Deliberate non-goals
|
|
66
|
+
|
|
67
|
+
- **prxref does not gate merges.** `review` exits 0 even when the review fails.
|
|
68
|
+
It is an advisor. Do not build a security control on its exit code.
|
|
69
|
+
- **Diff content is sent to the LLM endpoint you configure.** If your diffs are
|
|
70
|
+
sensitive, point prxref at an endpoint you trust. prxref does not choose or
|
|
71
|
+
contact any provider on its own.
|
|
72
|
+
- **Review output is model-generated and not authoritative.** Findings can be
|
|
73
|
+
wrong. Treat them as review comments, not as verified vulnerability reports.
|