Your codebase doesn't remember why.

import time
from payments.gateway import StripeClient
from orders.models import Order, PaymentAttempt

# Subsystem: docs/subsystems/payment_pipeline
# Chunk: docs/chunks/checkout_retry

def process_checkout(order: Order, token: str) -> PaymentAttempt:
    """Process payment with vendor-aware retry logic."""
    client = StripeClient(api_key=order.merchant.stripe_key)

    for attempt in range(3):
        try:
            result = client.charges.create(
                amount=order.total_cents,
                currency=order.currency,
                source=token,
                idempotency_key=f"{order.id}-{attempt}",
            )
            return PaymentAttempt.record(order, result, success=True)

        except client.RateLimitError:
            # Decision: docs/trunk/DECISIONS.md#stripe-retry-policy
            time.sleep(3)

        except client.CardError as e:
            return PaymentAttempt.record(order, e, success=False)

    raise CheckoutExhaustedError(order_id=order.id, attempts=3)
import time
from payments.gateway import StripeClient
from orders.models import Order, PaymentAttempt

def process_checkout(order: Order, token: str) -> PaymentAttempt:
    """Process payment with vendor-aware retry logic."""
    client = StripeClient(api_key=order.merchant.stripe_key)

    for attempt in range(3):
        try:
            result = client.charges.create(
                amount=order.total_cents,
                currency=order.currency,
                source=token,
                idempotency_key=f"{order.id}-{attempt}",
            )
            return PaymentAttempt.record(order, result, success=True)

        except client.RateLimitError:
            time.sleep(3)

        except client.CardError as e:
            return PaymentAttempt.record(order, e, success=False)

    raise CheckoutExhaustedError(order_id=order.id, attempts=3)

An agent reading this code knows where it came from, why it exists, and what it's allowed to change.

An agent reading this code has to guess why it exists.

Day 2

Vibe coding is magic on day 1. You describe what you want, the agent builds it, and it works.

Day 2, you ask for a change. The agent doesn't know why anything was built the way it was. It guesses. It breaks things. You start over, or you stop trusting it.

The problem isn't the agent. It's that your codebase contains only the result, not the reasoning.

How does it get there?

VE organizes work into chunks. Small, documented units of change. Before you write code, you write what you're trying to do and why. The agent implements against that intent, and the documentation stays connected to the code it produced.

This doesn't replace comments. You still want comments explaining what the code does. Chunks define something broader: the envelope of what correct looks like. An agent refactoring that code can see the invariants and the intent behind it, not just what each line does.

Define what you're trying to do and why. The goal captures the problem, the success criteria, and the constraints. It's the contract between you and the agent. A well-written goal means the agent doesn't have to guess your intent.

Break down how you'll get there. The plan is an ordered sequence of steps, each small enough to reason about in isolation. It references existing code, decisions, and subsystems so the agent knows what it's building on.

The agent writes code against documented intent. With the goal and plan as context, the agent implements each step and adds backreference comments that link the code back to the documentation that produced it. The codebase gains context as it grows.

Code references are updated and the chunk is closed. The documentation now accurately describes what shipped. Future agents discover this context by following backreferences in the code, learning progressively instead of needing everything upfront.

Recent research confirms what VE practitioners already know: agents don't benefit from being told everything upfront. They need to discover context progressively, at the point where it's relevant. That's what backreferences and chunk documentation create. A codebase that teaches the agent as it navigates.

The hardcoded retry

Look at the example above again. time.sleep(3). Any engineer would "fix" that to exponential backoff. Any agent would too.

But the backreference points to this:

Decision Record

Stripe retry policy. The vendor's rate limiter bans clients that retry faster than 3 seconds. We discovered this during the Nov 15 2024 incident when exponential backoff (starting at 100ms) triggered a 24-hour IP ban during peak checkout.

Fixed sleep of 3 seconds is the only correct retry interval. Do not change without re-testing against the vendor's rate limiter in staging.

2024-11-15
Code can look wrong and be exactly right. Without the reasoning, the next agent to touch it will "fix" it.

Retrofit, don't rewrite

You don't need to have used VE from the start. Run ve init in any existing project. Start documenting your next chunk of work. The backreferences accumulate. The codebase gets smarter one change at a time.

$ uv tool install vibe-engineer
Other install methods
$ pip install vibe-engineer
Open Source