Skip to content

Latest commit

 

History

History
322 lines (260 loc) · 11.1 KB

File metadata and controls

322 lines (260 loc) · 11.1 KB

Bugloop Architecture

An autonomous bug-fixing pipeline: errors become issues, issues become PRs, PRs get reviewed and merged — no human in the loop unless escalation is needed.

Pipeline Overview

[Error Monitor] → [Issue Creator] → [Bugsolver Agent] → [Draft PR] ←→ [Code Review] → [Merge]

Actors

Actor Role Trigger
Error Monitor Watches production logs/alerts for errors Continuous (server-side)
Issue Creator Files GitHub issues with context (stack trace, affected file, repro steps) Error detected
Bugsolver Agent Picks up assigned issues, enters build/test/eval loop, opens draft PR Issue assigned with label bug:autofix
Review Loop Addresses CodeRabbit / reviewer comments iteratively PR comment events
Merge Gate Marks PR ready-for-review when all comments resolved + CI green Zero unresolved threads + green CI

Phase 1: Issue Detection & Filing

The error monitor (already built via MCP) observes runtime errors and files GitHub issues:

Error detected → MCP tool call → gh issue create

Issue template requirements:

  • Title: Short error description
  • Body must include:
    • Stack trace / error log
    • Affected file(s) and line numbers
    • Reproduction steps (if determinable)
    • Severity tag
  • Labels: bug, bug:autofix
  • Assignee: bugsolver-agent (or bot account)

Phase 2: Issue Listener / Dispatcher

Option A: GitHub Actions (recommended for MVP)

# .github/workflows/bugloop-dispatch.yml
name: Bugloop Dispatch
on:
  issues:
    types: [assigned, labeled]

jobs:
  dispatch:
    if: contains(github.event.issue.labels.*.name, 'bug:autofix')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Bugsolver Agent
        env:
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          ISSUE_BODY: ${{ github.event.issue.body }}
        run: |
          # Install Claude Code CLI
          npm install -g @anthropic-ai/claude-code
          # Spawn agent with issue context
          claude --prompt "$(cat .bugloop/prompts/solve-issue.md)" \
            --env ISSUE_NUMBER=$ISSUE_NUMBER

Option B: Webhook Server (for more control)

                    ┌─────────────────────┐
GitHub Webhook ───→ │  Dispatcher Service  │
(issues.assigned)   │  (Node/Python/Go)    │
                    └────────┬────────────┘
                             │
                             ▼
                    ┌─────────────────────┐
                    │  Agent Spawner       │
                    │  - Clones repo       │
                    │  - Creates branch    │
                    │  - Launches Claude   │
                    └─────────────────────┘

Webhook server responsibilities:

  • Validate webhook signatures
  • Filter events (only bug:autofix labeled issues)
  • Manage agent lifecycle (spawn, monitor, kill if stuck)
  • Track state per issue (solving, pr-open, reviewing, merged)
  • Enforce concurrency limits

Phase 3: The Ralph Loop (Build/Test/Eval)

Once the bugsolver agent has the issue context, it enters an iterative loop:

┌─────────────────────────────────────────────┐
│                                             │
│   ┌──────────┐    ┌───────┐    ┌──────┐   │
│   │  Code     │───→│ Build  │───→│ Test  │  │
│   │  Changes  │    │        │    │       │  │
│   └──────────┘    └───────┘    └──┬───┘   │
│        ▲                           │        │
│        │         ┌──────────┐      │        │
│        └─────────│ Evaluate │◀─────┘        │
│                  └──────────┘               │
│                                             │
│   Exit condition: tests pass + build clean  │
└─────────────────────────────────────────────┘

Loop constraints:

  • Max iterations: 10 (configurable)
  • Timeout: 30 minutes per issue
  • If stuck after N iterations → label issue needs-human, unassign bot

Agent prompt structure:

  1. Read the issue (error context, stack trace, affected files)
  2. Explore the codebase for relevant code
  3. Hypothesize the fix
  4. Implement the change
  5. Run build + tests
  6. If failing → analyze failure, adjust, retry
  7. If passing → exit loop, proceed to PR

Phase 4: Draft PR Creation

After the ralph loop exits successfully:

gh pr create \
  --title "fix: [short description from issue]" \
  --body "Closes #${ISSUE_NUMBER}\n\n## Changes\n..." \
  --draft \
  --base main

PR body must include:

  • Closes #N to auto-link the issue
  • Summary of changes made
  • Test results (pass count, coverage delta)
  • Files modified

Phase 5: Code Review Resolution Loop

Once the draft PR is open, automated reviewers (CodeRabbit, etc.) will comment. The agent enters a second loop:

┌──────────────────────────────────────────────────────┐
│                                                      │
│   ┌────────────┐    ┌─────────────┐    ┌─────────┐ │
│   │ Wait for    │───→│ Read         │───→│ Address  │ │
│   │ comments    │    │ comments     │    │ comments │ │
│   └────────────┘    └─────────────┘    └────┬────┘ │
│        ▲                                     │      │
│        │              ┌──────────┐           │      │
│        └──────────────│ Re-run   │◀──────────┘      │
│                       │ tests    │                   │
│                       └──────────┘                   │
│                                                      │
│   Exit: zero unresolved threads + CI green           │
└──────────────────────────────────────────────────────┘

Implementation:

# .github/workflows/bugloop-review.yml
name: Bugloop Review Handler
on:
  pull_request_review_comment:
    types: [created]
  pull_request_review:
    types: [submitted]

jobs:
  handle-review:
    if: startsWith(github.event.pull_request.head.ref, 'bugloop/')
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.ref }}
      - name: Resolve Comments
        run: |
          claude --prompt "$(cat .bugloop/prompts/resolve-comments.md)" \
            --env PR_NUMBER=${{ github.event.pull_request.number }}

Comment resolution strategy:

  1. Fetch all unresolved review threads via gh api
  2. Group by file
  3. For each comment: understand the suggestion, apply fix, push commit
  4. Re-run tests after all comments addressed
  5. Reply to each thread confirming the fix

Phase 6: Ready-for-Review Gate

Conditions to mark PR ready:

  • All CodeRabbit comments resolved
  • All CI checks passing
  • No unresolved review threads
  • Diff is under size limit (e.g., < 500 lines changed)
# Check conditions
UNRESOLVED=$(gh api repos/:owner/:repo/pulls/$PR/reviews | jq '[.[] | select(.state == "CHANGES_REQUESTED")] | length')
CI_STATUS=$(gh pr checks $PR --json state | jq -r '.[] | select(.state != "SUCCESS") | .name')

if [ "$UNRESOLVED" -eq 0 ] && [ -z "$CI_STATUS" ]; then
  gh pr ready $PR
fi

State Machine

Each issue/PR moves through these states:

OPEN → ASSIGNED → SOLVING → PR_DRAFT → REVIEWING → READY → MERGED
                     │                      │
                     ▼                      ▼
                  ESCALATED             ESCALATED

State storage options:

  • GitHub issue/PR labels (simplest, visible)
  • A .bugloop/state.json in the repo (versioned)
  • External store (Redis/SQLite) for the webhook server approach

Directory Structure

bugloop/
├── .github/
│   └── workflows/
│       ├── bugloop-dispatch.yml      # Issue → Agent trigger
│       ├── bugloop-review.yml        # PR comment → Agent trigger
│       └── bugloop-gate.yml          # Ready-for-review check
├── .bugloop/
│   ├── config.yml                    # Loop limits, timeouts, labels
│   └── prompts/
│       ├── solve-issue.md            # Prompt template for bugsolver
│       └── resolve-comments.md       # Prompt template for review resolution
├── src/
│   ├── dispatcher/                   # Webhook server (Option B)
│   │   ├── server.ts
│   │   ├── webhook-handler.ts
│   │   └── agent-spawner.ts
│   ├── state/                        # State machine
│   │   └── machine.ts
│   └── gates/                        # Gate condition checks
│       └── ready-for-review.ts
├── ARCHITECTURE.md
└── README.md

Configuration

# .bugloop/config.yml
labels:
  trigger: "bug:autofix"
  in-progress: "bugloop:solving"
  needs-human: "bugloop:escalated"

limits:
  max_ralph_iterations: 10
  max_review_iterations: 5
  timeout_minutes: 30
  max_diff_lines: 500

branch_prefix: "bugloop/"

agents:
  bugsolver:
    assignee: "bugsolver-bot"
  reviewer:
    # CodeRabbit handles this automatically
    external: true

Guardrails & Escalation

  1. Iteration limits: After N failed attempts, label bugloop:escalated and unassign
  2. Timeout: Kill agent process after configured timeout
  3. Diff size: If changes exceed threshold, escalate for human review
  4. Branch protection: Require at least 1 human approval before merge (configurable)
  5. File restrictions: Agent cannot modify CI config, security-critical paths, or .bugloop/ itself
  6. Rollback: If post-merge monitoring detects regression, auto-revert and re-open issue

Future Extensions

  • Multi-repo support: Error in service A files issue in service A's repo
  • Priority queue: High-severity issues get solved first
  • Learning loop: Track success rate per error pattern, skip known-unfixable patterns
  • Cost tracking: Monitor API usage per issue resolution
  • Parallel solving: Multiple agents working on different issues concurrently
  • Human-in-the-loop mode: Agent proposes fix, waits for human approval before PR