pr-context-engine 0.1.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 (77) hide show
  1. pr_context_engine-0.1.0/.env.example +30 -0
  2. pr_context_engine-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
  3. pr_context_engine-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +16 -0
  4. pr_context_engine-0.1.0/.github/pull_request_template.md +15 -0
  5. pr_context_engine-0.1.0/.github/workflows/pr-review.yml +59 -0
  6. pr_context_engine-0.1.0/.github/workflows/release.yml +44 -0
  7. pr_context_engine-0.1.0/.gitignore +24 -0
  8. pr_context_engine-0.1.0/.python-version +1 -0
  9. pr_context_engine-0.1.0/CHANGELOG.md +22 -0
  10. pr_context_engine-0.1.0/CODE_OF_CONDUCT.md +27 -0
  11. pr_context_engine-0.1.0/CONFIG.md +80 -0
  12. pr_context_engine-0.1.0/CONTRIBUTING.md +60 -0
  13. pr_context_engine-0.1.0/LICENSE +21 -0
  14. pr_context_engine-0.1.0/PKG-INFO +211 -0
  15. pr_context_engine-0.1.0/PROJECT.md +481 -0
  16. pr_context_engine-0.1.0/README.md +181 -0
  17. pr_context_engine-0.1.0/action.yml +62 -0
  18. pr_context_engine-0.1.0/docs/design-decisions.md +87 -0
  19. pr_context_engine-0.1.0/pyproject.toml +57 -0
  20. pr_context_engine-0.1.0/src/__init__.py +1 -0
  21. pr_context_engine-0.1.0/src/analyzers/__init__.py +1 -0
  22. pr_context_engine-0.1.0/src/analyzers/ast_walker.py +91 -0
  23. pr_context_engine-0.1.0/src/analyzers/diff_parser.py +158 -0
  24. pr_context_engine-0.1.0/src/analyzers/risk_scorer.py +121 -0
  25. pr_context_engine-0.1.0/src/briefing/__init__.py +5 -0
  26. pr_context_engine-0.1.0/src/briefing/generator.py +229 -0
  27. pr_context_engine-0.1.0/src/briefing/prompt_templates.py +67 -0
  28. pr_context_engine-0.1.0/src/cli.py +329 -0
  29. pr_context_engine-0.1.0/src/config.py +118 -0
  30. pr_context_engine-0.1.0/src/context/__init__.py +1 -0
  31. pr_context_engine-0.1.0/src/context/codebase_index.py +382 -0
  32. pr_context_engine-0.1.0/src/context/git_history.py +225 -0
  33. pr_context_engine-0.1.0/src/fixes/__init__.py +1 -0
  34. pr_context_engine-0.1.0/src/fixes/confidence.py +60 -0
  35. pr_context_engine-0.1.0/src/fixes/fix_generator.py +152 -0
  36. pr_context_engine-0.1.0/src/github_api/__init__.py +3 -0
  37. pr_context_engine-0.1.0/src/github_api/comment_poster.py +95 -0
  38. pr_context_engine-0.1.0/src/llm/__init__.py +106 -0
  39. pr_context_engine-0.1.0/src/llm/anthropic_provider.py +32 -0
  40. pr_context_engine-0.1.0/src/llm/base.py +11 -0
  41. pr_context_engine-0.1.0/src/llm/gemini_provider.py +33 -0
  42. pr_context_engine-0.1.0/src/llm/groq_provider.py +30 -0
  43. pr_context_engine-0.1.0/src/llm/ollama_provider.py +41 -0
  44. pr_context_engine-0.1.0/tests/__init__.py +0 -0
  45. pr_context_engine-0.1.0/tests/eval/__init__.py +0 -0
  46. pr_context_engine-0.1.0/tests/eval/fixtures/01-simple-refactor.json +10 -0
  47. pr_context_engine-0.1.0/tests/eval/fixtures/02-auth-middleware.json +10 -0
  48. pr_context_engine-0.1.0/tests/eval/fixtures/03-db-migration.json +10 -0
  49. pr_context_engine-0.1.0/tests/eval/fixtures/04-config-update.json +10 -0
  50. pr_context_engine-0.1.0/tests/eval/fixtures/05-public-api-deleted.json +10 -0
  51. pr_context_engine-0.1.0/tests/eval/fixtures/06-hardcoded-api-key.json +15 -0
  52. pr_context_engine-0.1.0/tests/eval/fixtures/07-token-in-url.json +15 -0
  53. pr_context_engine-0.1.0/tests/eval/fixtures/08-retry-no-limit.json +15 -0
  54. pr_context_engine-0.1.0/tests/eval/fixtures/09-missing-null-check.json +15 -0
  55. pr_context_engine-0.1.0/tests/eval/fixtures/10-trivial-docfix.json +10 -0
  56. pr_context_engine-0.1.0/tests/eval/fixtures/11-multi-flag.json +10 -0
  57. pr_context_engine-0.1.0/tests/eval/fixtures/12-new-endpoint.json +10 -0
  58. pr_context_engine-0.1.0/tests/eval/fixtures/13-auth-bypass.json +15 -0
  59. pr_context_engine-0.1.0/tests/eval/fixtures/14-env-file-update.json +10 -0
  60. pr_context_engine-0.1.0/tests/eval/fixtures/15-dependency-update.json +10 -0
  61. pr_context_engine-0.1.0/tests/eval/rubric.md +95 -0
  62. pr_context_engine-0.1.0/tests/eval/test_briefings.py +543 -0
  63. pr_context_engine-0.1.0/tests/unit/__init__.py +0 -0
  64. pr_context_engine-0.1.0/tests/unit/test_anthropic_provider.py +39 -0
  65. pr_context_engine-0.1.0/tests/unit/test_ast_walker.py +100 -0
  66. pr_context_engine-0.1.0/tests/unit/test_briefing_generator.py +203 -0
  67. pr_context_engine-0.1.0/tests/unit/test_codebase_index.py +279 -0
  68. pr_context_engine-0.1.0/tests/unit/test_config.py +82 -0
  69. pr_context_engine-0.1.0/tests/unit/test_diff_parser.py +127 -0
  70. pr_context_engine-0.1.0/tests/unit/test_failover_provider.py +189 -0
  71. pr_context_engine-0.1.0/tests/unit/test_fix_generator.py +393 -0
  72. pr_context_engine-0.1.0/tests/unit/test_gemini_provider.py +34 -0
  73. pr_context_engine-0.1.0/tests/unit/test_git_history.py +319 -0
  74. pr_context_engine-0.1.0/tests/unit/test_groq_provider.py +34 -0
  75. pr_context_engine-0.1.0/tests/unit/test_ollama_provider.py +55 -0
  76. pr_context_engine-0.1.0/tests/unit/test_risk_scorer.py +178 -0
  77. pr_context_engine-0.1.0/uv.lock +1460 -0
@@ -0,0 +1,30 @@
1
+ # Copy this file to .env for local development. .env is gitignored — never commit it.
2
+
3
+ # ── Provider selection ────────────────────────────────────────────────────────
4
+ # Choose: groq (default) | gemini | ollama | anthropic
5
+ LLM_PROVIDER=groq
6
+
7
+ # ── Provider keys (only the selected provider's key is required) ──────────────
8
+
9
+ # Free Groq API key (no credit card): https://console.groq.com/keys
10
+ GROQ_API_KEY=your-groq-api-key-here
11
+
12
+ # Google Gemini key (fallback): https://aistudio.google.com/apikey
13
+ GEMINI_API_KEY=your-gemini-api-key-here
14
+
15
+ # Anthropic Claude key (BYO): https://console.anthropic.com/settings/keys
16
+ ANTHROPIC_API_KEY=your-anthropic-api-key-here
17
+
18
+ # Ollama (local, no key needed — just run `ollama serve`)
19
+ # OLLAMA_BASE_URL=http://localhost:11434
20
+ # OLLAMA_MODEL=qwen2.5-coder:7b
21
+
22
+ # ── GitHub ────────────────────────────────────────────────────────────────────
23
+ # A GitHub token with `pull-requests: write` scope.
24
+ # Locally, you can generate one with: gh auth token
25
+ GITHUB_TOKEN=your-github-token-here
26
+
27
+ # ── Fix suggestions (opt-in) ──────────────────────────────────────────────────
28
+ # Set to true to generate confidence-gated patch suggestions. Default: false.
29
+ # See CONFIG.md for full details.
30
+ ENABLE_FIXES=false
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something isn't working
4
+ labels: bug
5
+ ---
6
+
7
+ **What happened**
8
+ <!-- A clear description of the bug. -->
9
+
10
+ **To reproduce**
11
+ ```bash
12
+ # Command you ran
13
+ pr-context-engine review --pr N --repo owner/name
14
+ ```
15
+
16
+ **Expected behaviour**
17
+
18
+ **Actual behaviour** (include the full error / log output)
19
+
20
+ **Environment**
21
+ - OS:
22
+ - Python version (`python --version`):
23
+ - Package version (`pr-context-engine --version` or `pip show pr-context-engine`):
24
+ - LLM provider (`LLM_PROVIDER` value):
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an improvement
4
+ labels: enhancement
5
+ ---
6
+
7
+ **What problem does this solve?**
8
+ <!-- Describe the use case, not the implementation. -->
9
+
10
+ **What should the solution look like?**
11
+
12
+ **Alternatives you've considered**
13
+
14
+ **Would you be willing to open a PR?**
15
+ - [ ] Yes
16
+ - [ ] No
@@ -0,0 +1,15 @@
1
+ ## What changed
2
+
3
+ <!-- 2-3 sentences on the intent, not the line count. -->
4
+
5
+ ## Why
6
+
7
+ <!-- Link to the issue this closes, or explain the motivation. -->
8
+
9
+ ## Checklist
10
+
11
+ - [ ] `uv run ruff check src/ tests/` passes
12
+ - [ ] `uv run pytest tests/unit/ -v` passes
13
+ - [ ] New behaviour is covered by a unit test
14
+ - [ ] `CONFIG.md` updated if new env vars were added
15
+ - [ ] `CHANGELOG.md` entry added under `## Unreleased`
@@ -0,0 +1,59 @@
1
+ name: PR Context Briefing
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened]
6
+
7
+ jobs:
8
+ lint:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - uses: actions/setup-python@v5
13
+ with:
14
+ python-version: "3.12"
15
+ - name: Install uv
16
+ run: pip install uv
17
+ - name: Install dev dependencies
18
+ run: uv sync --group dev
19
+ - name: Lint
20
+ run: uv run ruff check src/ tests/
21
+
22
+ brief:
23
+ needs: lint
24
+ runs-on: ubuntu-latest
25
+ permissions:
26
+ pull-requests: write
27
+ contents: read
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 50 # tradeoff: enough history for most files, fast clone; see Milestone 6 note
32
+
33
+ - uses: actions/setup-python@v5
34
+ with:
35
+ python-version: "3.12"
36
+
37
+ - name: Install uv
38
+ run: pip install uv
39
+
40
+ - name: Restore index cache
41
+ uses: actions/cache@v4
42
+ with:
43
+ path: index.db
44
+ key: pr-engine-index-${{ github.event.pull_request.base.sha }}
45
+ restore-keys: pr-engine-index-
46
+
47
+ - name: Install dependencies
48
+ run: uv sync
49
+
50
+ - name: Generate briefing
51
+ env:
52
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53
+ LLM_PROVIDER: groq
54
+ GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
55
+ GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} # fallback (Milestone 7)
56
+ run: >
57
+ uv run pr-context-engine review
58
+ --pr ${{ github.event.pull_request.number }}
59
+ --repo ${{ github.repository }}
@@ -0,0 +1,44 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.12"
17
+
18
+ - name: Install uv
19
+ run: pip install uv
20
+
21
+ - name: Build distribution
22
+ run: uv build
23
+
24
+ - name: Upload dist artifact
25
+ uses: actions/upload-artifact@v4
26
+ with:
27
+ name: dist
28
+ path: dist/
29
+
30
+ publish:
31
+ needs: build
32
+ runs-on: ubuntu-latest
33
+ environment: pypi
34
+ permissions:
35
+ id-token: write # required for Trusted Publishing (OIDC — no PyPI token secret needed)
36
+ steps:
37
+ - name: Download dist artifact
38
+ uses: actions/download-artifact@v4
39
+ with:
40
+ name: dist
41
+ path: dist/
42
+
43
+ - name: Publish to PyPI
44
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,24 @@
1
+ # Byte-compiled / cached Python
2
+ __pycache__/
3
+ *.py[cod]
4
+
5
+ # Packaging / build artifacts
6
+ build/
7
+ dist/
8
+ *.egg-info/
9
+
10
+ # Virtual environment
11
+ .venv/
12
+
13
+ # Local secrets — never commit (see .env.example)
14
+ .env
15
+
16
+ # Test / tooling caches
17
+ .pytest_cache/
18
+ .ruff_cache/
19
+
20
+ # Generated codebase index (Milestone 5)
21
+ index.db
22
+
23
+ # Eval run output — generated on each run, not committed
24
+ tests/eval/scores.jsonl
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project uses [semantic versioning](https://semver.org/).
6
+
7
+ ## Unreleased
8
+
9
+ ## 0.1.0 — 2026-05-17
10
+
11
+ ### Added
12
+
13
+ - **Milestone 1** — End-to-end skeleton: Typer CLI entrypoint (`pr-context-engine review`), Groq LLM provider, GitHub diff fetch and PR comment posting, GitHub Actions workflow.
14
+ - **Milestone 2** — Pluggable LLM providers: `LLMProvider` abstract base, Gemini, Ollama, and Anthropic implementations, `LLM_PROVIDER` env var switching.
15
+ - **Milestone 3** — Real diff analysis: `diff_parser`, `ast_walker` (function/class name extraction), `risk_scorer` with located-issue objects (`file`, `line`, `snippet`).
16
+ - **Milestone 4** — Senior-voice prompt and structured briefing: four-section markdown output (What changed / Blast radius / Risk flags / Questions), terse system prompt.
17
+ - **Milestone 5** — Codebase index (RAG): `sqlite-vec` + `fastembed` local embeddings, semantic similar-chunk retrieval, `actions/cache` integration.
18
+ - **Milestone 6** — Git history context: per-file commit history, recent merged PR lookup, graceful shallow-clone degradation.
19
+ - **Milestone 7** — Provider failover: `FailoverProvider` (Groq → Gemini on 429), provider attribution in PR comment footer, unit test for failover path.
20
+ - **Milestone 8** — Confidence-gated fix suggestions: `fix_generator`, confidence gate (`high`/`medium` → suggestion block, `low` → prose), collapsed `<details>` + GitHub suggestion blocks, `ENABLE_FIXES` kill switch.
21
+ - **Milestone 9** — Eval harness: LLM-as-judge scoring across 5 rubric dimensions + fix correctness + calibration rate, `pytest tests/eval/` scorecard.
22
+ - **Milestone 10** — Open-source readiness: `action.yml` for one-line GitHub Action install, `--dry-run` flag, `quickstart` command, `LICENSE` (MIT), `CONTRIBUTING.md`, `CODE_OF_CONDUCT.md`, `CONFIG.md`, PyPI metadata, issue/PR templates.
@@ -0,0 +1,27 @@
1
+ # Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We pledge to make participation in this project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to a positive environment:
10
+
11
+ - Using welcoming and inclusive language
12
+ - Being respectful of differing viewpoints and experiences
13
+ - Gracefully accepting constructive criticism
14
+ - Focusing on what is best for the community
15
+
16
+ Examples of unacceptable behavior:
17
+
18
+ - Trolling, insulting/derogatory comments, and personal or political attacks
19
+ - Public or private harassment
20
+ - Publishing others' private information without explicit permission
21
+ - Other conduct which could reasonably be considered inappropriate in a professional setting
22
+
23
+ ## Enforcement
24
+
25
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting the maintainer directly. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
26
+
27
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,80 @@
1
+ # Configuration Reference
2
+
3
+ All configuration is via environment variables or CLI flags. CLI flags take precedence over env vars.
4
+
5
+ ## Minimal config (one API key is enough)
6
+
7
+ ```bash
8
+ export GROQ_API_KEY=<your-groq-key>
9
+ export GITHUB_TOKEN=<your-github-token>
10
+ pr-context-engine review --pr 42 --repo owner/name
11
+ ```
12
+
13
+ ## Full reference
14
+
15
+ ### Provider selection
16
+
17
+ | Env var | Default | Values | Description |
18
+ |---|---|---|---|
19
+ | `LLM_PROVIDER` | `groq` | `groq` \| `gemini` \| `ollama` \| `anthropic` | Primary LLM provider. |
20
+
21
+ ### API keys
22
+
23
+ | Env var | Required | Notes |
24
+ |---|---|---|
25
+ | `GROQ_API_KEY` | Yes (if `LLM_PROVIDER=groq`) | Free at https://console.groq.com/keys. ~1 000 req/day. |
26
+ | `GEMINI_API_KEY` | No | Failover when Groq is rate-limited. Also used as primary when `LLM_PROVIDER=gemini`. |
27
+ | `ANTHROPIC_API_KEY` | No | Required only when `LLM_PROVIDER=anthropic`. No free tier. |
28
+ | `GITHUB_TOKEN` | Yes (unless `--dry-run`) | Needs `pull-requests:write`. In Actions, use `${{ secrets.GITHUB_TOKEN }}`. |
29
+
30
+ ### Ollama
31
+
32
+ | Env var | Default | Description |
33
+ |---|---|---|
34
+ | `OLLAMA_BASE_URL` | `http://localhost:11434` | Ollama server URL. |
35
+ | `OLLAMA_MODEL` | `qwen2.5-coder:7b` | Model name to use via Ollama. |
36
+
37
+ ### Fix suggestions (opt-in)
38
+
39
+ | Env var | CLI flag | Default | Description |
40
+ |---|---|---|---|
41
+ | `ENABLE_FIXES` | `--enable-fixes` / `--no-enable-fixes` | `false` | Generate confidence-gated fix suggestions. Opt-in per repo. See [ADR-5](docs/design-decisions.md). |
42
+
43
+ ### Failover
44
+
45
+ Failover to Gemini is **automatic** whenever `GEMINI_API_KEY` is set, regardless of `LLM_PROVIDER`. The PR comment footer shows which provider was actually used (`via groq`, `via gemini (groq rate-limited)`, etc.).
46
+
47
+ To disable auto-failover, set `LLM_PROVIDER=gemini` explicitly — this makes Gemini the primary and there is no automatic fallback.
48
+
49
+ ## CLI flags (review command)
50
+
51
+ ```
52
+ pr-context-engine review [OPTIONS]
53
+
54
+ --pr INTEGER Pull request number. [required]
55
+ --repo TEXT Repository in owner/name form. [required]
56
+ --github-token TEXT GitHub token. Defaults to GITHUB_TOKEN env var.
57
+ --enable-fixes Generate fix suggestions (default off).
58
+ --no-enable-fixes Disable fix suggestions (default).
59
+ --dry-run Print briefing to stdout; do not post to GitHub.
60
+ --help Show this message and exit.
61
+ ```
62
+
63
+ ## CLI flags (quickstart command)
64
+
65
+ ```
66
+ pr-context-engine quickstart
67
+
68
+ Checks whether GROQ_API_KEY, GEMINI_API_KEY, and GITHUB_TOKEN are set and
69
+ whether the GitHub token has the correct scope. Prints exactly what is missing.
70
+ ```
71
+
72
+ ## GitHub Actions example (full config)
73
+
74
+ ```yaml
75
+ - uses: paramahastha/pr-context-engine@v1
76
+ with:
77
+ groq-api-key: ${{ secrets.GROQ_API_KEY }}
78
+ gemini-api-key: ${{ secrets.GEMINI_API_KEY }} # optional failover
79
+ enable-fixes: "true" # opt-in fix suggestions
80
+ ```
@@ -0,0 +1,60 @@
1
+ # Contributing
2
+
3
+ ## Development setup
4
+
5
+ Requires Python 3.12+ and [`uv`](https://docs.astral.sh/uv/).
6
+
7
+ ```bash
8
+ git clone https://github.com/paramahastha/pr-context-engine
9
+ cd pr-context-engine
10
+ uv sync --group dev
11
+ ```
12
+
13
+ Copy `.env.example` to `.env` and fill in your API keys.
14
+
15
+ ## Running tests
16
+
17
+ ```bash
18
+ # Unit tests (fast, no API calls)
19
+ uv run pytest tests/unit/ -v
20
+
21
+ # Eval harness (requires a provider key; uses LLM-as-judge)
22
+ uv run pytest tests/eval/ -v
23
+ ```
24
+
25
+ ## Lint
26
+
27
+ ```bash
28
+ uv run ruff check src/ tests/
29
+ ```
30
+
31
+ ## Local dry-run
32
+
33
+ ```bash
34
+ export GITHUB_TOKEN=$(gh auth token)
35
+ export GROQ_API_KEY=<your-key>
36
+ uv run pr-context-engine review --pr <N> --repo <owner/name> --dry-run
37
+ ```
38
+
39
+ ## Milestone philosophy
40
+
41
+ Each milestone is designed so the next milestone doesn't require painful refactors of the previous one. The key early decisions — CLI-core entrypoint (M1), provider abstraction (M2), and located-issue data shape in the risk scorer (M3) — exist specifically to make M7, M8, and M9 cheap. Don't skip milestones or reorder them.
42
+
43
+ ## Commit message format
44
+
45
+ ```
46
+ feat(milestone-N): description
47
+ fix(milestone-N): description
48
+ refactor: description
49
+ ```
50
+
51
+ ## Pull request checklist
52
+
53
+ - [ ] `uv run ruff check src/ tests/` passes
54
+ - [ ] `uv run pytest tests/unit/ -v` passes
55
+ - [ ] New behaviour is covered by a test in `tests/unit/`
56
+ - [ ] No new required env vars without updating `CONFIG.md`
57
+
58
+ ## Reporting bugs
59
+
60
+ Open an issue using the [bug report template](https://github.com/paramahastha/pr-context-engine/issues/new?template=bug_report.md).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kautsar
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.
@@ -0,0 +1,211 @@
1
+ Metadata-Version: 2.4
2
+ Name: pr-context-engine
3
+ Version: 0.1.0
4
+ Summary: An AI tool that reads every PR and posts a senior-engineer-style briefing.
5
+ Project-URL: Homepage, https://github.com/paramahastha/pr-context-engine
6
+ Project-URL: Repository, https://github.com/paramahastha/pr-context-engine
7
+ Project-URL: Issues, https://github.com/paramahastha/pr-context-engine/issues
8
+ Project-URL: Changelog, https://github.com/paramahastha/pr-context-engine/blob/main/CHANGELOG.md
9
+ Author-email: Kautsar <paramahastha@gmail.com>
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: ai,code-review,github,llm,pull-request
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Version Control :: Git
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: anthropic>=0.40
21
+ Requires-Dist: fastembed>=0.4
22
+ Requires-Dist: google-genai>=1.0
23
+ Requires-Dist: groq>=0.13
24
+ Requires-Dist: pygithub>=2.4
25
+ Requires-Dist: python-dotenv>=1.0
26
+ Requires-Dist: requests>=2.32
27
+ Requires-Dist: sqlite-vec>=0.1
28
+ Requires-Dist: typer>=0.12
29
+ Description-Content-Type: text/markdown
30
+
31
+ # PR Context Engine
32
+
33
+ [![CI](https://github.com/paramahastha/pr-context-engine/actions/workflows/pr-review.yml/badge.svg)](https://github.com/paramahastha/pr-context-engine/actions/workflows/pr-review.yml)
34
+ [![PyPI version](https://img.shields.io/pypi/v/pr-context-engine)](https://pypi.org/project/pr-context-engine/)
35
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
36
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
37
+
38
+ > An AI tool that reads every PR and writes the briefing — and the fixes — a senior engineer would, with the calibration data to prove it's not just guessing.
39
+
40
+ ## What it does
41
+
42
+ Every PR opens with three problems for the reviewer: _what is this actually doing_, _what could it break_, and _what should I push back on_. A diff doesn't answer any of those.
43
+
44
+ PR Context Engine reads the diff plus surrounding code, recent git history, and semantically similar code from elsewhere in the repo, then posts a terse briefing written like a senior backend engineer would write it:
45
+
46
+ ```markdown
47
+ ## PR Briefing
48
+
49
+ **What changed**
50
+ Refactors the session token storage from an in-memory dict to Redis, adding a
51
+ configurable TTL. The auth middleware is updated to hit Redis on every request.
52
+
53
+ **Blast radius**
54
+ Any caller of `get_session()` now depends on Redis being reachable. If Redis is
55
+ down, all authenticated requests will 401. The previous in-memory store had no
56
+ such single point of failure.
57
+
58
+ **Risk flags**
59
+ - `modifies_auth`: src/auth/session.py line 42 — `token = generate_token(user_id)`
60
+
61
+ **Questions for the reviewer**
62
+
63
+ 1. The Redis client is initialised once at import time — is there a reconnect
64
+ strategy if the connection drops mid-deploy?
65
+ 2. `SESSION_TTL` defaults to 3600 but the old in-memory store had no TTL — have
66
+ existing sessions been migrated or will they all expire immediately after deploy?
67
+ 3. There are no tests for the Redis-down path — is 401-on-outage the intended
68
+ degradation, or should it fall back to the old store?
69
+ ```
70
+
71
+ No praise. No filler. No "this LGTM." Just the context a reviewer needs.
72
+
73
+ ## Quickstart (5 minutes)
74
+
75
+ ### Option A — GitHub Action (recommended)
76
+
77
+ 1. Get a free [Groq API key](https://console.groq.com/keys) — no credit card.
78
+ 2. Add it as a secret: **Settings → Secrets → Actions → New secret** → `GROQ_API_KEY`.
79
+ 3. Enable write permissions: **Settings → Actions → General → Workflow permissions → Read and write**.
80
+ 4. Add this to `.github/workflows/pr-briefing.yml`:
81
+
82
+ ```yaml
83
+ name: PR Briefing
84
+ on:
85
+ pull_request:
86
+ types: [opened, synchronize, reopened]
87
+ jobs:
88
+ brief:
89
+ runs-on: ubuntu-latest
90
+ permissions:
91
+ pull-requests: write
92
+ contents: read
93
+ steps:
94
+ - uses: paramahastha/pr-context-engine@main
95
+ with:
96
+ groq-api-key: ${{ secrets.GROQ_API_KEY }}
97
+ ```
98
+
99
+ That's it. Every new PR gets a briefing comment automatically.
100
+
101
+ ### Option B — CLI (any CI or local)
102
+
103
+ ```bash
104
+ pipx install pr-context-engine
105
+ export GROQ_API_KEY=<your-groq-key>
106
+ export GITHUB_TOKEN=$(gh auth token)
107
+
108
+ # Check your setup first
109
+ pr-context-engine quickstart
110
+
111
+ # Dry-run: see the briefing without posting it
112
+ pr-context-engine review --pr 42 --repo owner/name --dry-run
113
+
114
+ # Post the real comment
115
+ pr-context-engine review --pr 42 --repo owner/name
116
+ ```
117
+
118
+ ## Switching LLM providers
119
+
120
+ Set `LLM_PROVIDER` to any of `groq` (default), `gemini`, `ollama`, or `anthropic`. Nothing downstream changes.
121
+
122
+ | Provider | Key env var | Notes |
123
+ |---|---|---|
124
+ | `groq` *(default)* | `GROQ_API_KEY` | Free, ~1 000 req/day, fast |
125
+ | `gemini` | `GEMINI_API_KEY` | Free-tier fallback; auto-engaged on Groq 429 |
126
+ | `ollama` | — | Local, offline, no rate limits |
127
+ | `anthropic` | `ANTHROPIC_API_KEY` | BYO key, no free tier |
128
+
129
+ **Automatic failover:** if `GEMINI_API_KEY` is set, the tool fails over to Gemini on any Groq 429 or error and notes it in the PR comment footer. See [ADR-7](docs/design-decisions.md).
130
+
131
+ ## Fix suggestions (opt-in)
132
+
133
+ When `ENABLE_FIXES=true`, the tool generates confidence-gated patch suggestions for located issues. Only `high`/`medium` confidence suggestions become one-click GitHub suggestion blocks; `low` confidence produces prose notes only. Max 3 suggestions per PR.
134
+
135
+ ```yaml
136
+ - uses: paramahastha/pr-context-engine@main
137
+ with:
138
+ groq-api-key: ${{ secrets.GROQ_API_KEY }}
139
+ enable-fixes: "true"
140
+ ```
141
+
142
+ See [ADR-5](docs/design-decisions.md) for why this is opt-in and confidence-gated.
143
+
144
+ ## Eval results
145
+
146
+ `pytest tests/eval/` produces a scorecard across five rubric dimensions (Accuracy, Blast radius, Risk flags, Question quality, Brevity) plus fix correctness and calibration rate.
147
+
148
+ ```
149
+ pytest tests/eval/ -v
150
+ ```
151
+
152
+ Results are committed to `tests/eval/scores/` so improvements are visible in git history. The headline metrics are **fix correctness rate** and **false-confidence rate** (when the model said `high` confidence, how often was the patch actually correct).
153
+
154
+ ## Architecture
155
+
156
+ ```
157
+ Front door A: Front door B:
158
+ GitHub Action wrapper pipx install + run in any CI / locally
159
+ (paramahastha/pr-context-engine@main)
160
+ │ │
161
+ └────────────┬────────────────────┘
162
+
163
+ ┌─────────────────────────────────────┐
164
+ │ CLI core (src/cli.py + orchestrator)│
165
+ └─────────────────────────────────────┘
166
+
167
+ ├──► analyzers/ diff → FileChange objects, AST symbols, risk flags
168
+ ├──► context/ git history, sqlite-vec codebase index (RAG)
169
+ ├──► briefing/ prompt assembly → LLM call → structured output
170
+ ├──► fixes/ confidence-gated patch suggestions (opt-in)
171
+ ├──► llm/ pluggable providers + FailoverProvider
172
+ └──► github_api/ fetch diff, post comment + suggestion blocks
173
+ ```
174
+
175
+ The CLI is the product; the GitHub Action is a thin wrapper. See [docs/architecture.md](docs/architecture.md) and [docs/design-decisions.md](docs/design-decisions.md).
176
+
177
+ ## Data & privacy
178
+
179
+ **What leaves your machine:**
180
+
181
+ - The PR diff and parsed metadata (file paths, function names, changed lines) are sent to the active LLM provider (Groq or Gemini by default).
182
+ - No source code beyond the diff is sent to any external API. The codebase index (RAG) runs entirely locally via `fastembed` + `sqlite-vec`.
183
+ - Git history and PR metadata are fetched from the GitHub API using your `GITHUB_TOKEN`.
184
+
185
+ **Provider data policies:**
186
+
187
+ - Groq and Gemini free tiers may use inputs for model improvement. See their respective privacy policies before using on private/sensitive repos.
188
+ - Use `LLM_PROVIDER=ollama` or `LLM_PROVIDER=anthropic` (with `ANTHROPIC_API_KEY`) if you need a provider with stronger data-isolation guarantees.
189
+ - The tool has no shared backend. Your API key, your quota, your data.
190
+
191
+ ## Configuration
192
+
193
+ See [CONFIG.md](CONFIG.md) for the full reference of every env var and flag.
194
+
195
+ ## Design decisions
196
+
197
+ See [docs/design-decisions.md](docs/design-decisions.md) for ADRs covering: why provider abstraction is built early, why SQLite over Pinecone, why fixes are opt-in, why MIT license, and more.
198
+
199
+ ## Cost
200
+
201
+ **$0/month** for a portfolio-scale project on public repos.
202
+
203
+ - GitHub Actions: free for public repos.
204
+ - Groq: free tier, ~1 000 req/day.
205
+ - Gemini fallback: free tier (~1 500 req/day).
206
+ - Local embeddings (`fastembed`): $0, no API.
207
+ - The tool has no shared backend — your usage costs stay yours regardless of how many repos adopt it.
208
+
209
+ ## Contributing
210
+
211
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Bug reports and feature requests go in [Issues](https://github.com/paramahastha/pr-context-engine/issues).