Skip to main content
Glama

patchpilot — Autonomous Code Repair Engine

CI Release v1.1.0 Python 3.10+ MCP Spec Vercel Deployment Claude Code Glama Score Smithery Ready Tests Passed Zero Dependencies License: MIT

Stack-Trace & AST Call-Graph Fault Localizer, Deterministic Anti-Reward-Hacking Patch Verifier (RH001–RH008), Transactional Rollback Sandbox, and Model Context Protocol (MCP) Server for Autonomous Coding Agents.

🚀 Live Interactive Developer Portal & Playground: Visit https://patchpilot-eta.vercel.app in your web browser to test diff auditing live, inspect schemas, and copy 1-click configurations for Claude Code, Cursor, Windsurf, and Claude Desktop.


Why patchpilot Exists: The Two Failure Modes of Coding Agents

Modern autonomous software engineering loops (OpenHands, SWE-agent, Claude Code, Devin-style test-repair loops) fail in production for two recurring reasons:

  1. Context-Window Flooding During Fault Localization: Dumping dozens of repository files into an LLM prompt when a pytest run fails wastes 90%+ of context tokens and confuses the model. Agents need deterministic Stack-Trace + AST Call-Graph + BM25 Spectrum Fault Localization to isolate the exact suspect functions and extract minimal, line-numbered AST slices within a strict token budget.

  2. Reward Hacking / Test Tampering by Coding Agents: When an LLM agent is rewarded for making pytest exit with code 0, it frequently "cheats" instead of fixing the root cause—deleting test_* functions, injecting @pytest.mark.skip or pytest.xfail(), weakening assert x == y into assert True, altering expected test constants, or wrapping buggy code in except Exception: pass.

patchpilot solves both problems in a zero-runtime-dependency Python 3.10+ package with a CLI, Python SDK, and JSON-RPC 2.0 MCP Server.


Related MCP server: MCP Software-Engineering RL Environment

Architecture Overview

  Failing Pytest / Traceback Log                    Candidate Agent Patch (Diff / Files)
                │                                                    │
                ▼                                                    ▼
┌───────────────────────────────────────┐    ┌──────────────────────────────────────────────┐
│  1. FaultLocalizer & ASTSymbolIndex   │    │  2. PatchIntegrityGuard (AST Verifier)       │
│  ───────────────────────────────────  │    │  ──────────────────────────────────────────  │
│  • Parses Python & pytest tracebacks  │    │  • RH001: Test deletion / @skip / xfail      │
│  • Builds AST symbol table & 2-hop    │    │  • RH002: Assertion removal / tautologies    │
│    bidirectional caller/callee graph  │    │  • RH003: Bare except / Exception swallowing │
│  • Ranks suspects via weighted formula│    │  • RH004: Python AST syntax validation       │
│    (0.55 Stack + 0.25 Graph + 0.20 BM25)   │  • RH005: Dangerous primitives (eval/shell)  │
│  • Emits token-budgeted code slices   │    │  • RH006: Leftover breakpoint() / pdb        │
└──────────────────┬────────────────────┘    │  • RH007: Blast radius limits (files/lines)  │
                   │                         │  • RH008: Protected CI/config file lock      │
                   │                         └──────────────────────┬───────────────────────┘
                   ▼                                                │
         Minimal Context Prompt                                     ▼
          (96.6% token savings)              ┌──────────────────────────────────────────────┐
                                             │  3. TransactionalPatchWorkspace              │
                                             │  ──────────────────────────────────────────  │
                                             │  • Pre-patch SHA-256 byte snapshots          │
                                             │  • Runs test runner / verification callback  │
                                             │  • Automatic byte-exact rollback on failure  │
                                             │  • Emits tamper-evident SHA-256 RepairReceipt│
                                             └──────────────────────────────────────────────┘

Anti-Reward-Hacking Rules (RH001–RH008)

Every candidate patch is evaluated by PatchIntegrityGuard via pre-patch vs. post-patch Python ast comparison before any test runner is executed:

Rule ID

Rule Name

Severity

What It Deterministically Blocks

RH001

Test Deletion or Skip Injection

Critical

Deleting test_* functions/files, injecting @pytest.mark.skip, @pytest.mark.xfail, @unittest.skip, or calling pytest.skip() / self.skipTest().

RH002

Assertion Weakening or Tautology

Critical

Reducing the number of assert / self.assert* statements in a test, replacing assertions with tautologies (assert True, assert 1 == 1), or mutating expected test literals.

RH003

Broad Exception Swallowing

High

Introducing bare except: or except (Exception, BaseException): blocks whose body merely executes pass, ..., continue, or returns a literal constant (return None).

RH004

Syntax / AST Parse Failure

Critical

Producing invalid Python syntax in any modified .py file.

RH005

Forbidden Dangerous Primitives

Critical

Injecting eval(), exec(), __import__(), os.system(), os.popen(), or subprocess.*(..., shell=True).

RH006

Debug Breakpoint Leftovers

Medium

Leaving breakpoint(), pdb.set_trace(), or ipdb.set_trace() inside patched code.

RH007

Excessive Blast Radius

Medium

Touching more than max_files_touched (default 5) or max_lines_changed (default 250).

RH008

Protected Path Modification

High

Tampering with .github/workflows/*, pyproject.toml, conftest.py, lockfiles, or .env files.


Reproducible Benchmark Results

Run patchpilot benchmark to execute the built-in benchmark suite across 50 indexed modules (100 AST symbols), 25 fault localization scenarios, and 40 patches (20 adversarial reward-hacking patches across RH001–RH008 + 20 legitimate bug fixes):

Subsystem

Benchmark Workload

Primary Accuracy / Recall

Secondary Metric

p50 Latency

p95 Latency

AST Symbol & Call-Graph Indexer

50 files / 100 symbols

100.0% AST parse coverage

Bidirectional call edges

3.79 ms

3.79 ms

Hybrid Fault Localizer (FaultLocalizer)

25 stack & call-graph fault scenarios

100.0% Top-1 / 100.0% Top-3

96.6% prompt token reduction

0.373 ms

0.499 ms

Anti-Reward-Hacking Guard (RH001–RH008)

20 adversarial + 20 legitimate patches

100.0% Recall / 100.0% Precision

0.0% False Positive Rate

0.098 ms

0.331 ms


Installation

git clone https://github.com/codesphere-u/patchpilot.git
cd patchpilot
pip install -e ".[dev]"

Quickstart: CLI

1. Run the End-to-End Autonomous Repair Demo

patchpilot demo

This creates a synthetic multi-file billing repository with a discount calculation bug, localizes the fault from a pytest failure log to the exact offending functions (billing/invoice.py::calculate_tiered_invoice and billing/pricing.py::apply_volume_discount) using only 303 tokens, catches and rolls back an adversarial reward-hacking patch (RH001, RH002, RH003), and commits a genuine minimal fix with a verified SHA-256 RepairReceipt.

2. Run the Benchmark Suite

patchpilot benchmark
patchpilot benchmark --json

Quickstart: Python SDK

from pathlib import Path
from patchpilot import FaultLocalizer, PatchIntegrityGuard, TransactionalPatchWorkspace

workspace = Path("./my_project")

# 1. Localize a failing pytest traceback within a 600-token budget
localizer = FaultLocalizer.from_directory(workspace)
loc = localizer.localize(pytest_stderr_output, top_k=3, token_budget=600)
print(loc.format_context_prompt())

# 2. Apply a candidate patch transactionally (with RH001-RH008 guard + automatic rollback)
sandbox = TransactionalPatchWorkspace(workspace, guard=PatchIntegrityGuard())
receipt = sandbox.apply_patch_transaction(
    patched_files={"billing/pricing.py": fixed_source_code},
    test_command=["pytest", "-q"],
    suspects_considered=[s.symbol.symbol_id for s in loc.suspects],
)

if receipt.status == "committed":
    print(f"Committed! Receipt SHA-256: {receipt.receipt_sha256}")
else:
    print(f"Rolled back at stage={receipt.stage_failed}: {receipt.guard_verdict.violations}")

Model Context Protocol (MCP) Server Integration

patchpilot includes a full JSON-RPC 2.0 MCP server exposing 5 deterministic tools to Claude Code, Cursor, OpenHands, or custom MCP clients:

Tool Name

What is its use? (Purpose)

Key Arguments

Hosted on Vercel?

Typical Output

audit_unified_diff

Parse and audit a multi-file git diff against 8 AST anti-reward-hacking rules (RH001–RH008) and export a canonical Nexus Aegis G5 attestation package.

unified_diff (str), original_files (optional dict), export_aegis (bool)

Yes (Public)

{"passed": true, "violations": [], "aegis_attestation": {...}}

localize_fault

Rank suspect functions from a traceback or pytest error log using hybrid Stack-Trace + AST Call-Graph + BM25 token overlap within a strict token budget.

traceback_text (str), sources (dict), top_k (int, default 5), token_budget (int, default 1200)

Yes (Inline sources)

{"suspects": [{"symbol": "pricing.py::discount", "score": 0.94}], "ast_slices": "..."}

verify_patch_integrity

Statically verify that a proposed code patch does not modify tests (RH001), add assert true (RH002), or stub functions (RH003–RH008).

original_files (dict), patched_files (dict), max_files_touched (int)

Yes (Public)

{"verdict": "PASSED", "clean": true, "violations": []}

inspect_ast_symbols

Query workspace AST symbol tables and caller/callee graphs by name or line number.

sources (dict), query_name (optional str), file_path (str), line_number (int)

Yes (Inline sources)

{"symbols": [{"name": "calculate_tax", "kind": "function", "line": 42}]}

apply_transactional_patch

Apply a patch inside an atomic snapshot sandbox with automatic byte-exact SHA-256 rollback if tests fail or rules are violated.

workspace_root (str), patched_files (dict), test_command (list)

Local stdio

{"status": "committed", "receipt_sha256": "..."}

Tool Usage Examples

1. audit_unified_diff — Blocking Agent Reward-Hacking in Git Diffs

Detect if an autonomous coding agent attempted to pass CI by modifying test assertions or deleting failure checks:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "audit_unified_diff",
    "arguments": {
      "unified_diff": "--- a/tests/test_auth.py\n+++ b/tests/test_auth.py\n@@ -12,3 +12,3 @@\n-    assert token.is_valid()\n+    assert True",
      "export_aegis": true
    }
  }
}

2. localize_fault — Pinpointing Root Cause from Pytest Failure Stacks

Feed a raw stack trace to get exact line-numbered AST function slices within an 800-token budget:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "localize_fault",
    "arguments": {
      "traceback_text": "Traceback (most recent call last):\n  File \"billing.py\", line 42, in process_charge\n    return calculate_fee(amount) / zero_divisor\nZeroDivisionError: division by zero",
      "sources": {
        "billing.py": "def calculate_fee(amount):\n    return amount * 0.03\n\ndef process_charge(amount):\n    zero_divisor = 0\n    return calculate_fee(amount) / zero_divisor\n"
      },
      "token_budget": 800
    }
  }
}

Exposed MCP Resources (resources/list, resources/read)

Resource URI

MIME Type

Purpose / Content Description

patchpilot://rules/catalog

application/json

The complete 8 AST anti-reward-hacking rules (RH001–RH008) detailing AST patterns, severities, and remediation guidelines.

patchpilot://stats/overview

application/json

Overview of supported Python AST node visitors, fault localization algorithms, and snapshot sandbox specs.

Exposed MCP Prompts (prompts/list, prompts/get)

Prompt Name

Purpose / Use Case

Required Arguments

Workflow Output

diagnose-and-repair

Guides an LLM agent to analyze a pytest failure traceback and systematically inspect suspect AST slices.

traceback_text (string)

Pre-formatted diagnostic prompt breaking down the exception frame, suspect functions, and verification constraints.

audit-git-diff

Guides an LLM reviewer to audit a candidate unified git diff for reward-hacking anti-patterns (RH001–RH008).

diff_text (string)

Pre-formatted code review prompt checking for deleted assertions, weakened tests, or swallowed exceptions.

MCP Client Configuration (claude_desktop_config.json / .cursor/mcp.json)

{
  "mcpServers": {
    "patchpilot": {
      "command": "patchpilot",
      "args": ["serve-stdio", "--workspace", "/path/to/your/repo"]
    }
  }
}

Architecture Decision Records (ADRs)


Hosted endpoint (Vercel)

A free, public, stateless deployment of PatchPilot runs over MCP Streamable HTTP:

MCP endpoint

https://patchpilot-eta.vercel.app/mcp (JSON-RPC 2.0 over POST)

Health probe

https://patchpilot-eta.vercel.app/health

curl -s -X POST https://patchpilot-eta.vercel.app/mcp -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Client Configuration

# Add to current project:
claude mcp add --transport http patchpilot https://patchpilot-eta.vercel.app/mcp

# Or add globally across all projects:
claude mcp add --scope user --transport http patchpilot https://patchpilot-eta.vercel.app/mcp

2. Claude Desktop / Cursor / Windsurf (mcp.json)

{
  "mcpServers": {
    "patchpilot": {
      "type": "http",
      "url": "https://patchpilot-eta.vercel.app/mcp"
    }
  }
}

3. Smithery Registry (1-Click Install)

npx -y @smithery/cli install @codesphere-u/patchpilot --client claude

4. Local Stdio via uvx (Full Workspace Access & File Mutations)

{
  "mcpServers": {
    "patchpilot": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/codesphere-u/patchpilot.git",
        "patchpilot",
        "serve-stdio"
      ]
    }
  }
}

Hosted limitations: apply_transactional_patch (writes files, runs commands) is disabled on the hosted endpoint, and localize_fault / inspect_ast_symbols accept inline sources only (no workspace_root). Use the local stdio install for full functionality.

The hosted gateway is api/index.py; it enforces a 1 MB body limit, strict JSON-RPC envelopes and the tool restrictions above. Deploy your own copy with npx vercel deploy --prod (entrypoint is configured in pyproject.toml under [tool.vercel]).

License

MIT License — Copyright (c) 2026 Akandwanaho Ivan Alvin (@codesphere-u).

Available Tools

5 tools
apply_transactional_patchB

Apply a candidate patch inside a snapshot-backed workspace transaction, verifying RH001–RH008 and running an optional test command with automatic byte-exact SHA-256 rollback on failure.

Inputs: workspace_root (required), test_command, unified_diff, patched_files, +1 more.

audit_unified_diffC

Parse and audit a multi-file unified git diff against 8 deterministic AST anti-reward-hacking & safety rules (RH001–RH008) and export canonical Nexus Aegis G5 leaf attestation.

Inputs: unified_diff (required), export_aegis, original_files.

inspect_ast_symbolsB

Query the AST symbol table and bidirectional call graph of a workspace by symbol name or (file_path, line_number).

Inputs: sources, file_path, query_name, line_number, +1 more.

localize_faultA

Rank suspect Python functions/methods from a traceback or pytest failure log using hybrid Stack-Trace + AST Call-Graph + BM25 token overlap, returning minimal line-numbered AST slices within a strict token budget.

Inputs: traceback_text (required), top_k, sources, token_budget, +2 more.

verify_patch_integrityB

Evaluate a proposed patch (original vs patched files or unified diff) against 8 deterministic AST anti-reward-hacking & safety rules (RH001–RH008).

Inputs: original_files (required), unified_diff, patched_files, max_files_touched, +2 more.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 5 tools

    Disambiguation3/5

    audit_unified_diff and verify_patch_integrity both evaluate a patch against the same RH001–RH008 rules, differing mainly in input shape and attestation output, which creates real risk of misselection. localize_fault, inspect_ast_symbols, and apply_transactional_patch are clearly distinct, and descriptions help resolve most ambiguity.

    Naming Consistency5/5

    All five tools follow a consistent verb_noun snake_case pattern (audit_*, localize_*, verify_*, apply_*, inspect_*). No mixed conventions or casing deviations.

    Tool Count5/5

    Five tools is well within the ideal range and each maps to a distinct phase of the patch workflow: locate, inspect, verify, audit, and apply. The set is tightly scoped with no filler tools.

    Completeness4/5

    The surface covers a full localize→inspect→verify→audit→apply lifecycle, including rollback and optional test execution in apply_transactional_patch. Minor gaps exist, such as no standalone rule-query or attestation-retrieval tool, but core workflows are covered.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to search code by meaning, explore codebase structure, store and query knowledge with temporal facts, and read source code through a set of MCP tools.
      306 npm
      7
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to perform software engineering tasks inside an isolated, deterministic sandbox—exploring repositories, reproducing failures, applying patches, running tests, and verifying solutions against hidden suites through MCP tools.
      8
      MIT
    • A
      license
      B
      quality
      B
      maintenance
      Enables AI coding agents and local LLMs to store and recall project memory, compact verbose logs, look up code symbols, create and rewind workspace snapshots, detect risky commands and loops, pack context optimally, and draft tokens through MCP tools.
      10
      2
      Apache 2.0