bug2patch
v0.1.0
Published
Turn a GitHub issue URL into a regression test, a verified patch, and a PR-ready summary.
Maintainers
Readme
Bug2Patch turns a GitHub issue URL into a regression test, a verified patch, and a PR-ready summary in one npm package.
No speculative suggestions. Proof included.
Table of Contents
- The Problem
- The Solution
- Quick Start
- How It Works
- Demo
- Output Artifacts
- Installation
- Usage
- Architecture
- Project Structure
- Tech Stack
- Configuration
- Running Tests
- Scope & Limitations
- Roadmap
- Credits
- Hackathon Submission
The Problem
Every AI coding assistant will happily say "here's a possible fix."
For a maintainer, that sentence is the beginning of work, not the end.
Before a fix can be merged it needs:
- Proof the bug exists — a test that fails on the unpatched code
- The smallest safe change — not a rewrite, not a refactor
- Proof the fix works — the same test passing after the patch
- Reviewable artifacts — a diff and test logs a reviewer can trust
No AI tool today produces all four automatically. Bug2Patch does.
The Solution
Bug2Patch is a local pipeline that takes a GitHub issue URL, proves the bug, writes a regression test and a minimal fix via OpenAI Codex, re-proves the code is now correct, and drops a final.diff and summary.md you can attach to a PR in seconds.
GitHub Issue URL → Clone → Baseline Tests → Codex → Patch → Final Tests → ArtifactsBefore Bug2Patch:Issue opened → hours of triage → write test → attempt fix → re-run tests → write PR body
After Bug2Patch:Issue opened → one command → done
Quick Start
# 1 — clone and install
git clone https://github.com/<your-org>/bug2patch.git
cd bug2patch
npm install
# 2 — run the deterministic demo (no API key needed)
node bin/bug2patch.js \
--issue-url demo/bug2patch-demo-python/ISSUE_1.md \
--auto-apply-demo-fix
# 3 — open the results
ls runs/$(ls -t runs | head -1)/How It Works
| Step | What Happens | Module |
|------|-------------|--------|
| 1 — Fetch Issue | Parses the GitHub URL, calls the REST API to pull title and body. Supports local .md issue files for offline demos. | github_issue.py |
| 2 — Clone & Branch | Clones the target repo into a timestamped run directory. Creates an isolated branch bug2patch/issue-<N>. | repo_ops.py |
| 3 — Detect Project | Confirms the repo is a Python project and picks the right pytest command (or falls back to python -m pytest). | src/projectDetector.js |
| 4 — Baseline Tests | Runs pytest against the unmodified repo and saves the result. Exit code 1 proves the bug exists. | test_runner.py |
| 5 — Build Prompt | Fills prompts/bugfix_prompt.md with the issue details, repo name, branch, and test command. Instructs Codex to add a failing test first, then apply the smallest fix. | src/codexRunner.js |
| 6 — Run Codex | Executes codex exec automatically when the CLI is available. Falls back to codex_instructions.txt for manual completion. | src/codexRunner.js |
| 7 — Capture Diff | Runs git diff HEAD and parses changed files and line stats. | src/diffParser.js |
| 8 — Final Tests | Re-runs pytest. Exit code 0 proves the fix works and no regressions were introduced. | src/testRunner.js |
| 9 — Write Artifacts | Saves final.diff, final_test.json, summary.md, and run_manifest.json into the run directory. | src/summaryWriter.js, src/runHistory.js |
Demo
The Demo Issue
The bundled demo poses a real bug in calculate_discount():
calculate_discount(price=100, quantity=0, discount_percent=10)
→ returns 10.0 # WRONG — zero items should mean zero discount
→ expected 0.0What Bug2Patch Produces
baseline_test.json — bug confirmed:
{
"command": "pytest -q",
"exit_code": 1,
"stderr": "AssertionError: assert 10.0 == 0.0"
}final.diff — minimal, reviewable patch:
--- a/src/pricing.py
+++ b/src/pricing.py
@@ -1,9 +1,9 @@
def calculate_discount(price: float, quantity: int, discount_percent: float) -> float:
- if discount_percent <= 0:
+ if discount_percent <= 0 or quantity <= 0:
return 0.0
- if quantity <= 1:
+ if quantity == 1:
--- a/tests/test_pricing.py
+++ b/tests/test_pricing.py
@@ -16,3 +16,6 @@
+def test_zero_quantity_returns_zero_discount():
+ assert calculate_discount(100, 0, 10) == 0.0final_test.json — fix proven:
{
"command": "pytest -q",
"exit_code": 0,
"stdout": "demo validation passed"
}Output Artifacts
Every run creates a folder at runs/<timestamp>-issue-<N>/ containing:
| File | Description |
|------|-------------|
| issue.json | Parsed issue title, body, number, and repo metadata |
| baseline_test.json | pytest result before any fix — proves the bug exists |
| bugfix_prompt.md | The structured prompt sent to Codex |
| codex_instructions.txt | Manual instructions if Codex CLI is unavailable |
| final.diff | Minimal patch diff — ready for git apply or a PR |
| final_test.json | pytest result after the fix — proves it works |
| summary.md | PR-ready summary: issue, fix approach, changed files, test results |
| run_manifest.json | Full run metadata for audit, history index, and re-runs |
| codex_execution.json | (When Codex runs) Full Codex execution output |
| codex_last_message.txt | (When Codex runs) Final message from the Codex session |
Installation
Prerequisites
| Requirement | Version | Notes |
|-------------|---------|-------|
| Node.js | 18+ | node --version to check |
| Git | Any recent | Must be on PATH |
| Python | 3.10+ | Required for pytest-based target repos and the demo fixers |
| pytest | 8.0+ | Installed in the target repo, not by Bug2Patch itself |
| Codex CLI | Latest | Optional — only needed for live GitHub issues with --runner-mode codex |
Step-by-Step
1 — Clone the repository
git clone https://github.com/<your-org>/bug2patch.git
cd bug2patch2 — Install the package
npm install3 — Verify
npm testUsage
Deterministic demo — no API key needed
Run the bundled single-file demo with an auto-applied known fix:
node bin/bug2patch.js \
--issue-url demo/bug2patch-demo-python/ISSUE_1.md \
--auto-apply-demo-fixMulti-file deterministic demo
Tests Bug2Patch across a multi-file repository:
node bin/bug2patch.js \
--issue-url demo/bug2patch-demo-python-multifile/ISSUE_2.md \
--auto-apply-demo-fixHeuristic auto-fix — simple guard-clause bug
For supported issue patterns (function should return a known value when a parameter is zero):
node bin/bug2patch.js \
--issue-url demo/bug2patch-generic-simple/ISSUE_3.md \
--auto-apply-simple-fixHeuristic auto-fix — empty / None input
For functions that should handle None or empty-string inputs gracefully:
node bin/bug2patch.js \
--issue-url demo/bug2patch-generic-empty/ISSUE_4.md \
--auto-apply-simple-fixLive GitHub issue via Codex
Requires the Codex CLI installed and authenticated:
node bin/bug2patch.js \
--issue-url https://github.com/<owner>/<repo>/issues/<number> \
--runner-mode codexRe-run an existing run after manual edits
If Codex wasn't available and you applied the fix manually:
node bin/bug2patch.js --rerun-run-dir runs/<run-id>Use a specific Python interpreter
node bin/bug2patch.js \
--issue-url <issue> \
--python-bin /usr/local/bin/python3.11
# Or via environment variable:
export BUG2PATCH_PYTHON_BIN=/usr/local/bin/python3.11Launch the local API and dashboard
Browse run history and artifacts in a browser:
node bin/bug2patch.js api --port 8000
# Then open http://localhost:8000Entry-point shortcuts (after npm install -g or npm link)
bug2patch --issue-url <issue>
bug2patch api --port 8000Architecture
Bug2Patch is a terminal-first, local-first pipeline. A single Node orchestrator (src/runJob.js) coordinates all modules. All state lives on disk inside the run folder — nothing is held in memory between steps, making every run inspectable and re-runnable.
Design Principles
- Local-first — No cloud services required for the demo path. Everything runs on a developer laptop.
- Fail fast, log always — Malformed URLs raise immediately; test failures are captured and stored, not swallowed.
- Continue on partial success — A "no diff" state is valid; the summary explains next steps rather than crashing.
- Cheap re-runs —
--rerun-run-dirreuses the existing clone; no re-clone needed. - No magic — Every decision (which test command, which fix) is logged to an artifact file for full auditability.
Error Handling
| Condition | Behaviour |
|-----------|-----------|
| Malformed issue URL | Raises ValueError immediately with a clear message |
| Clone failure | Raises — run directory is not created |
| pytest not found | Falls back to Python regression check for demo; logs the error |
| Codex CLI unavailable | Saves codex_instructions.txt; run continues to capture available artifacts |
| No diff after Codex | Skips final tests; summary.md explains next steps |
| Final tests fail | Captured and saved; summary flags the failure for review |
Project Structure
bug2patch/
│
├── src/ # Core npm library modules
│ ├── cli.js # CLI argument parsing and dispatch
│ ├── runJob.js # Orchestration entrypoint — coordinates all steps
│ ├── issue.js # GitHub REST API fetch + local issue file loader
│ ├── repoOps.js # git clone, branch creation, diff capture
│ ├── projectDetector.js # Python project + pytest command detection
│ ├── testRunner.js # Shell command executor → structured JSON result
│ ├── codexRunner.js # Prompt builder, codex exec runner, manual fallback
│ ├── diffParser.js # Git diff parser → changed files + line stats
│ ├── simpleAutoFixer.js # Heuristic guard-clause / empty-input fixer
│ ├── demoFixer.js # Deterministic auto-fix for bundled demo repos
│ ├── runHistory.js # run_manifest.json persistence + history index
│ └── summaryWriter.js # PR-ready summary.md generator
│
├── apps/
│ ├── api/ # Local REST API — serves run history + artifacts
│ └── web/ # Dashboard scaffold — browse runs in a browser
│
├── prompts/
│ └── bugfix_prompt.md # Codex prompt template (filled at runtime)
│
├── demo/ # Bundled demo repos and issue files
│ ├── bug2patch-demo-python/ # Single-file demo + ISSUE_1.md
│ ├── bug2patch-demo-python-multifile/ # Multi-file demo + ISSUE_2.md
│ ├── bug2patch-generic-simple/ # Generic guard-clause demo + ISSUE_3.md
│ └── bug2patch-generic-empty/ # Empty-input demo + ISSUE_4.md
│
├── runs/ # Per-run artifact output (git-ignored)
│ └── <timestamp>-issue-<N>/
│ ├── issue.json
│ ├── baseline_test.json
│ ├── bugfix_prompt.md
│ ├── codex_instructions.txt
│ ├── final.diff
│ ├── final_test.json
│ ├── summary.md
│ └── run_manifest.json
│
├── tests/ # Bug2Patch self-tests
├── test/ # Node test suite
├── assets/ # README images and diagrams
├── bin/ # npm CLI entrypoint
├── package.json
└── README.mdTech Stack
| Layer | Technology | Purpose |
|-------|-----------|---------|
| Language | Node.js 18+ | Orchestration, API, file I/O |
| AI Agent | OpenAI Codex CLI (codex exec) | Writes regression tests + patches |
| Validation | pytest 8.0+ | Proves bug exists, proves fix works in target repos |
| Version Control | Git (via subprocess) | Clone, branch, diff |
| Issue Source | GitHub REST API v3 | Fetch issue title + body |
| Dependencies | npm built-ins only (+ external tools) | Zero extra runtime dependencies |
| Local API | Custom HTTP server | Browse run history + artifacts |
| CI / Self-tests | node:test | Bug2Patch module tests |
Why no frameworks?
Bug2Patch's orchestration is intentionally dependency-light. Zero extra runtime dependencies means:
- Installs in seconds anywhere Node runs
- No dependency conflicts with the repos it clones and tests
- Easier to audit, fork, and extend
Configuration
CLI flags
| Flag | Description | Default |
|------|-------------|---------|
| --issue-url | GitHub issue URL or local .md file path | required |
| --runner-mode | auto, manual, or codex | auto |
| --auto-apply-demo-fix | Apply the known demo fix automatically | false |
| --auto-apply-simple-fix | Apply heuristic guard-clause fix | false |
| --rerun-run-dir | Rerun using an existing run directory | — |
| --python-bin | Python interpreter path for pytest | python3 |
Environment variables
| Variable | Description |
|----------|-------------|
| BUG2PATCH_PYTHON_BIN | Override Python interpreter for test execution |
| GITHUB_TOKEN | Optional — increases GitHub API rate limit for live issue fetching |
Running Tests
Run Bug2Patch's own test suite:
npm testExpected output:
test/issue.test.js ... ok
test/projectDetector.test.js ... ok
...
----------------------------------------------------------------------
Ran N tests in 0.Xs
OKScope & Limitations
What v1 supports
| Capability | Status |
|------------|--------|
| Public GitHub issue URLs | Supported |
| Local demo issue files (offline) | Supported |
| Small Python repos with pytest | Supported |
| Automatic codex exec execution | Supported |
| Heuristic guard-clause auto-fix | Supported |
| Heuristic None / empty-input fix | Supported |
| Deterministic demo runs | Supported |
| Re-run against existing run directory | Supported |
| Run history API + dashboard scaffold | Supported |
| Local-only execution | Supported |
What v1 does not support
| Limitation | Notes |
|------------|-------|
| Private repositories | GitHub token not wired to clone yet |
| Non-Python repositories | project_detector.py is Python-only today |
| Large monorepos / Docker setups | Assumes a simple pytest-at-root structure |
| Automatic PR creation | gh pr create output is a stretch goal |
| Cloud / hosted deployment | MVP is local-only by design |
| Parallel runs | Each invocation is a single serial pipeline |
Roadmap
| Priority | Feature |
|----------|---------|
| High | gh pr create integration — auto-open a PR from the run artifacts |
| High | Private repo support via GITHUB_TOKEN in clone |
| High | Widen heuristic fixer to cover more edge-case patterns |
| Medium | SQLite run history replacing history.json |
| Medium | Branch cleanup helpers for completed runs |
| Medium | Richer dashboard UI with live run status |
| Low | Non-Python repo support (Node/Jest, Ruby/RSpec) |
| Low | Parallel multi-issue processing |
Credits
Built by:
