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.
Files changed (48) hide show
  1. prxref-0.2.0/.gitignore +11 -0
  2. prxref-0.2.0/CHANGELOG.md +106 -0
  3. prxref-0.2.0/CONTRIBUTING.md +101 -0
  4. prxref-0.2.0/LICENSE +21 -0
  5. prxref-0.2.0/PKG-INFO +155 -0
  6. prxref-0.2.0/README.md +134 -0
  7. prxref-0.2.0/SECURITY.md +73 -0
  8. prxref-0.2.0/docs/deploy.md +119 -0
  9. prxref-0.2.0/docs/env-vars.md +50 -0
  10. prxref-0.2.0/docs/forges.md +71 -0
  11. prxref-0.2.0/docs/llm.md +61 -0
  12. prxref-0.2.0/examples/bitbucket-pipelines.yml +32 -0
  13. prxref-0.2.0/examples/github-actions-inline.yml +47 -0
  14. prxref-0.2.0/examples/gitlab-ci.yml +28 -0
  15. prxref-0.2.0/pyproject.toml +72 -0
  16. prxref-0.2.0/src/prxref/__init__.py +3 -0
  17. prxref-0.2.0/src/prxref/cli.py +214 -0
  18. prxref-0.2.0/src/prxref/config.py +147 -0
  19. prxref-0.2.0/src/prxref/forges/__init__.py +0 -0
  20. prxref-0.2.0/src/prxref/forges/base.py +101 -0
  21. prxref-0.2.0/src/prxref/forges/bitbucket.py +265 -0
  22. prxref-0.2.0/src/prxref/forges/github.py +190 -0
  23. prxref-0.2.0/src/prxref/forges/gitlab.py +369 -0
  24. prxref-0.2.0/src/prxref/formatter.py +197 -0
  25. prxref-0.2.0/src/prxref/llm.py +41 -0
  26. prxref-0.2.0/src/prxref/llm_backends.py +242 -0
  27. prxref-0.2.0/src/prxref/orchestrator.py +406 -0
  28. prxref-0.2.0/src/prxref/parser.py +110 -0
  29. prxref-0.2.0/src/prxref/prompts/.gitkeep +0 -0
  30. prxref-0.2.0/src/prxref/prompts/summary.md +11 -0
  31. prxref-0.2.0/src/prxref/prompts/worker.md +62 -0
  32. prxref-0.2.0/src/prxref/quality.py +265 -0
  33. prxref-0.2.0/src/prxref/reviewer.py +183 -0
  34. prxref-0.2.0/src/prxref/triage.py +367 -0
  35. prxref-0.2.0/src/prxref/webhooks.py +261 -0
  36. prxref-0.2.0/tests/__init__.py +0 -0
  37. prxref-0.2.0/tests/test_cli.py +294 -0
  38. prxref-0.2.0/tests/test_config.py +207 -0
  39. prxref-0.2.0/tests/test_forge_gitlab.py +362 -0
  40. prxref-0.2.0/tests/test_formatter.py +204 -0
  41. prxref-0.2.0/tests/test_integration.py +616 -0
  42. prxref-0.2.0/tests/test_llm_backends.py +334 -0
  43. prxref-0.2.0/tests/test_orchestrator.py +474 -0
  44. prxref-0.2.0/tests/test_parser.py +84 -0
  45. prxref-0.2.0/tests/test_quality.py +255 -0
  46. prxref-0.2.0/tests/test_reviewer.py +246 -0
  47. prxref-0.2.0/tests/test_triage.py +280 -0
  48. prxref-0.2.0/tests/test_webhooks.py +470 -0
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ dist/
7
+ *.egg-info/
8
+ .env
9
+ .superpowers/
10
+ .claude/
11
+ docs/superpowers/
@@ -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.
@@ -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.