Skip to content

benitezfede/prflow

Repository files navigation

PR Flow Graph

Review code changes as a directed graph, not a file list.

Traditional code review tools show diffs file-by-file in alphabetical order. This forces reviewers to mentally reconstruct the code flow — you might review utils.ts before handler.ts even though the handler is the entry point. PR Flow Graph visualizes PR changes as an interactive directed graph starting from entry points (functions with no upstream callers in the diff) and lets you navigate downstream through the call chain.

Works for both human reviewers and AI agents.

TypeScript Next.js License


How it works

GitHub PR URL
     │
     ▼
 Fetch files & contents (GitHub API)
     │
     ▼
 Parse ASTs with tree-sitter (WASM)
     │
     ▼
 3-pass graph construction
   Pass 1: Extract function/class definitions
   Pass 2: Resolve imports
   Pass 3: Match call sites → build edges
     │
     ▼
 Filter to changed functions (diff overlap)
     │
     ▼
 Topological sort → review order + entry points
     │
     ▼
 Dagre layout (left-to-right DAG)
     │
     ▼
 Interactive React Flow visualization

Features

Graph visualization

  • Functions grouped by file, expandable/collapsible
  • Color-coded by change type: green (added), red (deleted), yellow (modified)
  • Animated edges for calls, dashed for imports
  • Zoom controls, pan, and interactive minimap
  • "Connected only" toggle — select a file, filter to its downstream subgraph

Code review

  • Click any function to see its scoped diff (side-by-side)
  • Mark functions as reviewed, track progress
  • Review order follows the dependency graph, not alphabetical

Keyboard navigation

Key Action
j / Next function in review order
k / Previous function
r Mark current as reviewed
n Jump to next unreviewed
Esc Deselect / close diff panel

Agent API — structured endpoints for AI-powered review (no layout data, just semantics):

  • GET /api/agent/summary — PR shape, risk profile, review strategy
  • GET /api/agent/review-plan — ordered steps, clusters, dependency chains

Supported languages: TypeScript, JavaScript, Python


Quick start

Prerequisites

Install and run

git clone https://github.com/montecarlodata/prflow.git
cd prflow
npm install

# Set your GitHub token
echo "GITHUB_TOKEN=ghp_your_token_here" > .env.local

npm run dev

Open http://localhost:3000, paste a PR URL, and explore the graph.

Run tests

npm test            # single run
npm run test:watch  # watch mode

Agent API

These endpoints return semantic review data optimized for LLM consumption — no pixel positions, just what to review, in what order, and why.

Both accept either explicit params or a full PR URL:

GET /api/agent/summary?url=https://github.com/owner/repo/pull/123
GET /api/agent/review-plan?url=https://github.com/owner/repo/pull/123&verbosity=standard

GET /api/agent/summary

Lightweight PR shape for triage.

{
  "pr": { "owner": "acme", "repo": "api", "number": 42, "headSha": "abc123" },
  "shape": {
    "totalNodes": 12,
    "totalEdges": 8,
    "independentFlows": 2,
    "entryPoints": ["handleRequest", "migrateSchema"],
    "languages": { "typescript": 10, "python": 2 }
  },
  "hubs": [
    { "name": "DatabaseClient", "file": "src/db/client.ts", "connections": 6 }
  ],
  "riskProfile": { "high": 3, "medium": 4, "low": 5 },
  "strategy": "2 independent flows. `handleRequest` flow (8 fns, 120 lines). `migrateSchema` flow (4 fns, 45 lines). Hub: `DatabaseClient` has 6 connections — review it early."
}

GET /api/agent/review-plan

Step-by-step review plan with dependency chains.

Verbosity levels:

Level Includes Target tokens (20 nodes)
minimal steps with order, name, file, lines, role, risk <500
standard + calledBy/calls, riskReasons, clusters, dependencies <2000
full + reviewHint, clusterId ~3000
{
  "pr": { "owner": "acme", "repo": "api", "number": 42, "headSha": "abc123", "baseSha": "def456" },
  "stats": {
    "totalSteps": 12,
    "totalAdditions": 145,
    "totalDeletions": 32,
    "independentFlows": 2,
    "filesChanged": 5
  },
  "steps": [
    {
      "order": 1,
      "nodeId": "src/handler.ts::handleRequest",
      "name": "handleRequest",
      "file": "src/handler.ts",
      "lines": [15, 42],
      "type": "function",
      "changeType": "modified",
      "additions": 20,
      "deletions": 5,
      "role": "entry_point",
      "calledBy": [],
      "calls": ["src/handler.ts::validate", "src/db/client.ts::query"],
      "risk": "high",
      "riskReasons": ["entry_point", "large_diff"]
    }
  ],
  "clusters": [
    {
      "id": 0,
      "label": "handler.ts",
      "nodeIds": ["src/handler.ts::handleRequest", "src/handler.ts::validate"],
      "reason": "2 related functions in handler.ts",
      "suggestedReviewOrder": ["src/handler.ts::handleRequest", "src/handler.ts::validate"]
    }
  ],
  "dependencies": [
    {
      "from": "src/handler.ts::handleRequest",
      "to": "src/handler.ts::validate",
      "reason": "Review `handleRequest` before `validate` — `handleRequest` calls `validate`."
    }
  ]
}

Agent workflow

1. GET /api/agent/summary?url=<PR>           → Quick triage: size, risk, flows
2. GET /api/agent/review-plan?url=<PR>       → Ordered steps + dependencies
3. For each step, read the file at the given line range
4. Follow topological order — review callees before callers
5. Batch comments by cluster

Architecture

src/
├── app/
│   ├── page.tsx                                  # Landing page — PR URL input
│   ├── [owner]/[repo]/pull/[number]/page.tsx     # PR review page
│   └── api/
│       ├── graph/route.ts                        # GET /api/graph → LayoutGraph JSON
│       ├── graph/contents/route.ts               # GET /api/graph/contents → file diffs
│       └── agent/
│           ├── summary/route.ts                  # GET /api/agent/summary
│           └── review-plan/route.ts              # GET /api/agent/review-plan
├── components/
│   ├── FlowGraph.tsx          # React Flow graph with file grouping, zoom, minimap
│   ├── FileNode.tsx           # Expandable file container node
│   ├── FunctionNode.tsx       # Individual function node
│   ├── DiffPanel.tsx          # Side-by-side diff viewer (scoped to function)
│   └── ReviewProgress.tsx     # Floating progress bar
├── hooks/
│   ├── useGraph.ts            # Fetch + cache graph data
│   └── useReviewState.ts      # localStorage review progress
└── lib/
    ├── github/
    │   ├── client.ts          # Octokit wrapper (GITHUB_TOKEN)
    │   ├── pr.ts              # Fetch PR files + contents (p-limit concurrency)
    │   └── types.ts           # PRFile, FileContent, PRContext
    ├── parser/
    │   ├── engine.ts          # Tree-sitter init, WASM loading, language detection
    │   ├── types.ts           # SymbolDefinition, CallSite, ImportStatement
    │   └── languages/
    │       ├── typescript.ts  # TS/JS adapter — definitions, calls, imports
    │       └── python.ts      # Python adapter
    ├── graph/
    │   ├── builder.ts         # 3-pass graph construction + diff filtering
    │   ├── topological.ts     # Entry points + Kahn's algorithm
    │   ├── layout.ts          # Dagre left-to-right layout
    │   ├── cache.ts           # Shared in-memory LRU cache
    │   └── types.ts           # GraphNode, GraphEdge, PRGraph, LayoutGraph
    └── agent/
        ├── types.ts           # ReviewPlan, ReviewStep, PRSummary
        ├── parse-pr-url.ts    # GitHub PR URL parser
        ├── graph-analysis.ts  # Adjacency, risk, components, strategy
        ├── review-plan.ts     # buildReviewPlan(graph, verbosity)
        └── summary.ts         # buildPRSummary(graph)

Key technical decisions

Decision Choice Why
AST parsing web-tree-sitter (WASM) Works in Node.js + Turbopack without native bindings
Graph layout Dagre (LR) Purpose-built for DAGs, deterministic left-to-right layout
Visualization React Flow DOM-based custom nodes, built-in pan/zoom/minimap
Diff rendering react-diff-viewer-continued Scoped to function line range, syntax highlighting
Import resolution Syntactic (relative only) Good enough for most PRs; avoids needing full project context
Caching In-memory LRU keyed by headSha Same PR + same commit = same graph, shared between visual and agent APIs

License

MIT

About

Review code changes as a directed graph, not a file list

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages