Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Contributing

## Setup

Python 3.12+ and Node 22+.

```bash
pip install -e ".[dev]"
python -m playwright install chromium # optional; needed for UI screenshot tests
cd ui && npm install && npm run build && cd ..
loadpath --help
```

## Tests

```bash
pytest
cd ui && npm test
node --test desktop/*.test.mjs
```

CI installs Chromium and runs the full suite. The demo fixture is `fixtures/demo_monorepo`.

## Screenshots

README images live in `docs/screenshots/` and are produced by Playwright:

```bash
LOADPATH_SCREENSHOT_DIR=docs/screenshots python -m pytest tests/e2e/test_ui_screenshots.py
```

Do not commit a 3D screenshot from headless Chromium unless `[data-testid=graph-3d-canvas]` is present. This environment often falls back to “WebGL is unavailable.”

## UI

The React app in `ui/` is built into `src/loadpath/static/` and served by `loadpath serve`.

```bash
cd ui
npm run build # writes into src/loadpath/static/
npm run dev # Vite, proxies /api to the Django-shaped FastAPI server
```

If you change `ui/` and only run `loadpath serve`, you are looking at a stale bundle until you `npm run build`.

## Desktop

```bash
pip install -e .
cd ui && npm install && npm run build && cd ..
cd desktop && npm install && npm start
```

Requires Python 3.12+ on `PATH` (`python` on Windows, `python3` elsewhere), or set `LOADPATH_PYTHON`.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Loadpath contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
115 changes: 103 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Loadpath

[![CI](https://github.com/Modsofthenation/PR-Reviewer/actions/workflows/ci.yml/badge.svg)](https://github.com/Modsofthenation/PR-Reviewer/actions/workflows/ci.yml)

Review as **load-path inspection** on a Django + React architecture graph. Not another hunk-comment bot.

A change is a force. Loadpath traces where that force travels until it hits a sink — HTTP response, UI, Celery/Dramatiq job, migration, permission — then scores whether you have enough evidence to merge.
Expand All @@ -19,39 +21,93 @@ On the demo monorepo that path is:

plus the jobs the view enqueues (`send_invoice_email.delay`, `rebuild_ledger.send`).

![Review screen with impact graph](docs/screenshots/review.png)

It is a local CLI, a desktop UI, and an MCP server you can point Cursor at. Not a SaaS. Tokens stay on the machine in `~/.loadpath/settings.json`.

## App

`loadpath serve --port 7345` opens a local desktop-style UI: icon rail, labeled toolbar, merge-box confidence, and an inspectable impact graph. The same process hosts MCP at `/mcp` (OAuth). Tokens stay on the machine in `~/.loadpath/settings.json`. AI is used **only** for residual uncertainty the graph cannot close. Two dozen themes (Obsidian, Nord, Neon Noir, Synthwave, Phosphor, Sakura, Citrus, Paper, high-contrast, …) live in Settings and `localStorage`. Last repo, git range, and SCM slug are remembered the same way. Copy the markdown brief, or post **one** PR comment (updated in place) from the Review tab. Keyboard: `1`–`5` switches tabs. Outside Settings and Pull requests, `⌘`/`Ctrl`+`Enter` runs a review.
`loadpath serve --port 7345` opens a local desktop-style UI: icon rail, labeled toolbar, merge-box confidence, and an inspectable impact graph. The same process hosts MCP at `/mcp` (OAuth). AI is used **only** for residual uncertainty the graph cannot close. Twenty-four themes live in Settings and `localStorage`. Last repo, git range, and SCM slug are remembered the same way. Copy the markdown brief, or post **one** PR comment (updated in place) from the Review tab. Keyboard: `1`–`5` switches tabs. Outside Settings and Pull requests, `⌘`/`Ctrl`+`Enter` runs a review.

### Empty review

Until a repo is indexed and a range is walked, Review is an onboarding card — not a blank graph.

![Empty review onboarding](docs/screenshots/review-empty.png)

### Review

Confidence brief, read-order, clusters, architecture findings on the impact path, residual list, and the subgraph for the git range. Review walks the **indexed** graph (incremental refresh by default).

![Review](docs/screenshots/review.png)
![Review with brief and impact graph](docs/screenshots/review.png)

### Node inspector

Click a node. The inspector answers *what is this, what feeds it, what does it call, what would break* — not a dump of the indexer row.

![Inspector on InvoiceSerializer](docs/screenshots/review-inspector.png)

### Architecture

Index a repo first. The architecture tab is the full typed graph plus `loadpath.yml` contexts and rules — not a PR diff. Findings here are repo-wide; review then scopes them to the change.

![Architecture](docs/screenshots/architecture.png)
![Architecture graph and findings](docs/screenshots/architecture.png)

### Impact graph

Toggle **This review** (impact subgraph) vs **Indexed architecture** (the repo map). Dashed edges are inferred (URL/Zod overlap); solid edges are extracted or generated-client stitches.
Toggle **This review** (impact subgraph) vs **Indexed architecture** (the repo map). Dashed edges are inferred (URL/Zod overlap); solid edges are extracted or generated-client stitches. 2D is the default; 3D is available when WebGL is.

![Impact graph, this review](docs/screenshots/graph.png)

![Impact graph](docs/screenshots/graph.png)
![Indexed architecture in the graph tab](docs/screenshots/graph-architecture.png)

### Pull requests

GitHub and Bitbucket via API tokens from Settings. Pick a PR and jump to a branch-range review.
GitHub and Bitbucket via API tokens from Settings. Pick a PR and jump to a branch-range review. The screenshot uses a fixture PR so the tab is not empty.

![Pull requests list](docs/screenshots/pull-requests.png)

### Repo explorer

![Pull requests](docs/screenshots/pull-requests.png)
Browse the filesystem, pick a project root. Loadpath remembers recent workspaces.

![Repo explorer](docs/screenshots/explorer.png)

### Settings

GitHub / Bitbucket tokens; AI providers (Anthropic, OpenAI, Grok/xAI, DeepSeek, Cursor-compatible, Ollama). Residual analysis only — Loadpath does not comment every hunk.
Appearance (all 24 themes), GitHub / Bitbucket tokens, and AI providers (Anthropic, OpenAI, Grok/xAI, DeepSeek, Cursor-compatible, Ollama). Residual analysis only — Loadpath does not comment every hunk.

![Settings with theme grid](docs/screenshots/settings.png)

### MCP consent

When Cursor (or another client) connects over HTTP MCP, Loadpath does not silently grant access. You get a local consent page: client name, Loadpath issuer URL, optional PIN. Approve or deny. Tokens stay in `~/.loadpath/oauth.json`.

![Settings](docs/screenshots/settings.png)
![MCP consent](docs/screenshots/mcp-consent.png)

## Themes

Default is **Obsidian**. Settings lists every palette; the shots below are the same Review screen under nine of them.

<table>
<tr>
<td align="center"><strong>Obsidian</strong><br/><img src="docs/screenshots/theme-obsidian.png" alt="Obsidian theme" /></td>
<td align="center"><strong>Nord</strong><br/><img src="docs/screenshots/theme-nord.png" alt="Nord theme" /></td>
<td align="center"><strong>Neon noir</strong><br/><img src="docs/screenshots/theme-neon-noir.png" alt="Neon noir theme" /></td>
</tr>
<tr>
<td align="center"><strong>Synthwave</strong><br/><img src="docs/screenshots/theme-synthwave.png" alt="Synthwave theme" /></td>
<td align="center"><strong>Phosphor</strong><br/><img src="docs/screenshots/theme-phosphor.png" alt="Phosphor theme" /></td>
<td align="center"><strong>Paper</strong><br/><img src="docs/screenshots/theme-paper.png" alt="Paper theme" /></td>
</tr>
<tr>
<td align="center"><strong>Sakura</strong><br/><img src="docs/screenshots/theme-sakura.png" alt="Sakura theme" /></td>
<td align="center"><strong>Citrus</strong><br/><img src="docs/screenshots/theme-citrus.png" alt="Citrus theme" /></td>
<td align="center"><strong>High contrast</strong><br/><img src="docs/screenshots/theme-high-contrast.png" alt="High contrast theme" /></td>
</tr>
</table>

Also shipping: Solarized Dark/Light, Forest, Rose Pine, Midnight Amber, Volcano, Lavender, Aurora, Biolume, Carbon, Seafoam, Peach Fuzz, Cotton Candy, Clear Sky, Coral Reef. High contrast is a first-class theme, not an afterthought.

## Install

Expand All @@ -64,6 +120,8 @@ cd ui && npm install && npm run build && cd ..
loadpath --help
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for tests, screenshot regeneration, and the Electron app.

## Desktop app (Windows, macOS, Linux)

Electron wraps the same local app: it starts the Loadpath backend and opens it in a native window. Tokens still live in `~/.loadpath/settings.json`.
Expand Down Expand Up @@ -115,6 +173,29 @@ loadpath mcp

**Flow:** `index` builds the architecture graph → `architecture` shows contexts and rule hits on the whole repo → `review` walks that same graph for a git range. The app mirrors this: Index registers a workspace, Architecture inspects it, Review traces a change through it.

The bundled demo checkout is [`fixtures/demo_monorepo`](fixtures/demo_monorepo) (Django billing API + React invoice UI). Copy it and make **two** commits so `HEAD~1` is a real range — the fixture itself is not a git repo, and a single commit leaves the default range empty.

```bash
cp -R fixtures/demo_monorepo /tmp/acme-billing
cd /tmp/acme-billing
git init -b main
git add -A && git commit -m "baseline"
# Same contract tweak the screenshots use:
python3 - <<'PY'
from pathlib import Path
p = Path("backend/billing/serializers.py")
p.write_text(p.read_text().replace(
'fields = ["id", "customer_id", "total", "status"]',
'fields = ["id", "customer_id", "total", "status"]\n extra_kwargs = {"total": {"required": True}}',
))
PY
git add -A && git commit -m "tighten Invoice.total contract"
loadpath index /tmp/acme-billing
loadpath serve --open
```

Then point the UI at `/tmp/acme-billing`, or pick it from the repo explorer. `loadpath serve` always boots the app; it does not take a repo path. Default range is `HEAD~1`…`HEAD`.

## MCP (Cursor, Claude, ChatGPT, Gemini)

`loadpath serve` exposes Streamable HTTP MCP at `/mcp`, protected with OAuth 2.1 (PKCE, dynamic client registration, Client ID Metadata Documents). Cloud hosts need HTTPS; set `--public-url` to the public origin when tunneling. `--oauth-pin` adds a PIN on the consent page.
Expand All @@ -138,7 +219,7 @@ MCP URL: `https://your-tunnel.example/mcp` (or `http://127.0.0.1:7345/mcp` on th
}
```

**Cursor / Claude / ChatGPT / Gemini (HTTP + OAuth)** — add that MCP URL in the host’s connectors. The first connect opens a consent page on the Loadpath machine. Tokens stay in `~/.loadpath/oauth.json`.
**Cursor / Claude / ChatGPT / Gemini (HTTP + OAuth)** — add that MCP URL in the host’s connectors. The first connect opens a consent page on the Loadpath machine.

Tools: `list_workspaces`, `init_repo`, `index_repo`, `architecture`, `review`, `detect_repo`, `list_pull_requests`, `post_review_comment`. `review` returns the load-path brief (confidence, sinks, reviewers) — not hunk comments.

Expand Down Expand Up @@ -193,6 +274,8 @@ AST is enough for review. If you need live `_meta` (db_table, resolved relations

**Stitch (the moat):** OpenAPI from Spectacular/schema files first; generated clients (`generated/`, orval, openapi-typescript) as high-confidence `consumed_by_client`; fallback URL-template matching and serializer/Zod field overlap marked **inferred**.

Frontend roots prefer `frontend/src`, `frontend`, `web/src`, `client/src`, `ui/src`, `src-ui/src` — not a Python package `src/` and not `docs` / docs-site trees. `app/` is a Django root candidate.

## Architecture rules (`loadpath.yml`)

| Rule | Meaning |
Expand Down Expand Up @@ -247,10 +330,14 @@ node --test desktop/*.test.mjs
| `tests/e2e/test_mcp_oauth.py` | OAuth metadata/DCR/PKCE, consent, CIMD, MCP `review` stays on the billing load path |
| `tests/e2e/test_index_architecture_flow.py` | index snapshot, review without index, review walking an existing graph |
| `tests/e2e/test_brokers_and_django.py` | Celery + Dramatiq sinks, actor-only PR, non-idempotent Dramatiq warning, destructive migration, cross-context blocker, boot overlay, management commands, beat/canvas |
| `tests/e2e/test_ui_screenshots.py` | Playwright: Architecture, Review, Impact graph, Pull requests, Settings → `docs/screenshots/` |
| `tests/e2e/test_ui_screenshots.py` | Playwright screenshots (tmpdir by default; set `LOADPATH_SCREENSHOT_DIR=docs/screenshots` to regenerate README assets) |
| `desktop/*.test.mjs` | Electron sidecar command, health-wait, and external-URL allowlist |

CI installs Chromium and runs the full suite.
To regenerate the README screenshots:

```bash
LOADPATH_SCREENSHOT_DIR=docs/screenshots python -m pytest tests/e2e/test_ui_screenshots.py
```

## Demo fixture

Expand All @@ -259,3 +346,7 @@ CI installs Chromium and runs the full suite.
## What this is not

Not CodeRabbit (comments without a closed impact set). Not a CodeScene clone (we do not replace its hotspot maps; we only score churn/coupling on the load path). Not django-orm-lens (we do not boot an ER explorer; we reuse its N+1 / cascade / blast-radius heuristics inside the typed graph). Not a generic SCIP call graph. The product is review as load-path inspection.

## License

MIT. See [LICENSE](LICENSE). Vulnerability reports: [SECURITY.md](SECURITY.md).
7 changes: 7 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Security

Please report vulnerabilities privately to the repository owner (`Modsofthenation` on GitHub). Do not open a public issue for unreleased security problems.

Once this repository is public, enable [GitHub private vulnerability reporting](https://docs.github.com/code-security/security-advisories/working-with-repository-security-advisories/configuring-private-vulnerability-reporting-for-a-repository) so researchers can use Security Advisories. The `/security/advisories/new` form 404s until that setting is on.

Tokens and OAuth state live on the machine that runs Loadpath (`~/.loadpath/`); treat that host as trusted.
Binary file modified docs/screenshots/architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/explorer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/graph-architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/mcp-consent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/pull-requests.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/review-empty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/review-inspector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/review.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/screenshots/settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-citrus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-high-contrast.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-neon-noir.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-nord.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-obsidian.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-paper.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-phosphor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-sakura.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/theme-synthwave.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ version = "0.1.0"
description = "Architecture-typed impact graphs for Django + React pull requests."
readme = "README.md"
requires-python = ">=3.12"
license = { text = "MIT" }
authors = [{ name = "Loadpath" }]
keywords = ["django", "react", "code-review", "architecture", "mcp"]
classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.12",
"Topic :: Software Development :: Quality Assurance",
]
dependencies = [
"fastapi>=0.115.0",
"uvicorn[standard]>=0.32.0",
Expand All @@ -31,6 +38,11 @@ dev = [
"playwright>=1.49.0",
]

[project.urls]
Homepage = "https://github.com/Modsofthenation/PR-Reviewer"
Repository = "https://github.com/Modsofthenation/PR-Reviewer"
Issues = "https://github.com/Modsofthenation/PR-Reviewer/issues"

[project.scripts]
loadpath = "loadpath.cli:app"

Expand Down
Loading
Loading