Module 2: Mental Models for AI Code

Circuit Breaker: Verification Checkpoints

Circuit Breaker: Verification Checkpoints

Capsule overview

In the previous capsule you learned how to supervise (Managing an Intern). Now you need to know when to pause. The Circuit Breaker pattern comes from software engineering: when a service fails, the circuit breaker trips and stops requests to avoid cascades of errors. Applied to your flow with AI code, the concept is similar: you define checkpoints where you pause, verify, and decide whether to continue or stop.

Without checkpoints, the flow with Claude Code becomes dangerous. You ask it to generate 5 files, you accept them all without pausing, you commit, and you discover the problem 3 days later when something fails in production. With checkpoints, you pause after each file (or each logical group), verify what matters, and only continue when you're confident in what you already have.

This capsule teaches you to define checkpoints for your workflow, what to verify at each one, and when to "trip the breaker" — stop completely because something isn't right.


The Circuit Breaker Pattern in Software

The original pattern

In distributed software, the Circuit Breaker pattern prevents cascading failures:

Without a Circuit Breaker:
Service A → Service B (down) → timeout → retry → timeout → retry
→ Service A runs out of threads
→ Service C that depends on A also fails
→ Cascade of failures

With a Circuit Breaker:
Service A → Service B (down) → the circuit breaker trips
→ Service A gets an immediate error
→ It doesn't waste resources on useless retries
→ It can respond with a fallback
→ It recovers when Service B comes back

The adaptation to code review

The same logic applies to your flow with AI code:

Without checkpoints:
You ask for 5 files → You accept the 5 → Commit → Push → Deploy
→ You discover a bug in file 2
→ Files 3, 4, 5 depended on file 2
→ Everything is wrong → Complete revert

With checkpoints:
You ask for 5 files → You review file 1 → OK → You continue
→ You review file 2 → Issue in the logic → PAUSE
→ You fix file 2 → You regenerate files 3-5 with the fix
→ You review 3, 4, 5 → OK → Commit

The difference is dramatic: without checkpoints, an error in an early file contaminates everything that follows. With checkpoints, you detect and fix before the error propagates.


Types of Checkpoints

The 4 checkpoints of the AI code flow

Checkpoint 1: AFTER GENERATING
├── Is the output what you asked for?
├── Is the overall structure correct?
├── Is there anything clearly wrong?
└── → Decision: continue, regenerate, or edit

Checkpoint 2: BEFORE INTEGRATING
├── Does the code integrate with the existing code?
├── Are the imports real?
├── Do the interfaces match?
└── → Decision: integrate, adjust, or discard

Checkpoint 3: BEFORE COMMIT
├── Do the tests pass?
├── Does the linter pass?
├── Does the diff show only the expected changes?
└── → Decision: commit, adjust, or revert

Checkpoint 4: BEFORE MERGE/DEPLOY
├── Is the code review complete?
├── Do the CI tests pass?
├── Are there unmitigated risks?
└── → Decision: merge, iterate, or block

What to verify at each checkpoint

Each checkpoint has a different scope. You don't verify the same thing in all of them — that would be inefficient.

Checkpoint 1: After generating

This is the most frequent checkpoint. You apply it every time Claude Code generates output.

# Claude Code just generated this file.
# CHECKPOINT 1: What do I verify?

# 1. Is it what I asked for?
#    I asked for a product search endpoint.
#    Is the output a product search endpoint?

# 2. Is the structure reasonable?
#    Does it use FastAPI? Does it have validation? Does it have error handling?

# 3. Is there anything clearly wrong?
#    Imports I don't recognize? Logic that doesn't make sense?
#    A completely different approach from what I expected?

Typical time: 1-3 minutes for simple code, 5-10 minutes for complex code.

Checkpoint 2: Before integrating

This checkpoint applies when the generated code must coexist with existing code.

# I have an existing app and Claude Code generated a new module.
# CHECKPOINT 2: Does it integrate correctly?

# 1. Do the imports reference modules that exist in MY project?
from app.models.user import User          # Does this module exist?
from app.core.security import get_current_user  # Does this function exist?
from app.db.session import get_db         # Is this the pattern I use?

# 2. Do the interfaces match?
#    If the existing module expects User.id as int,
#    does the new module treat it as int? Or does it assume string?

# 3. Are there naming conflicts?
#    Does the new module define functions with names that already exist?

Typical time: 3-8 minutes.

Checkpoint 3: Before commit

This checkpoint is technical — you verify that everything works before recording the state.

# CHECKPOINT 3: Before commit

# 1. Do the tests pass?
pytest tests/ -v
# If there are failing tests → DON'T commit. Investigate first.

# 2. Does the linter pass?
ruff check .
mypy .
# Lint errors can indicate real problems, not just style.

# 3. Is the diff what you expect?
git diff --stat
# Did only what should change actually change?
# Are there unexpected files modified?

git diff
# Read the entire diff. Does it all make sense?

Typical time: 2-5 minutes.

Checkpoint 4: Before merge/deploy

This is the final and most rigorous checkpoint.

CHECKPOINT 4: Before merge

1. Is the code review complete?
   - Did I apply Managing an Intern with the correct levels?
   - Did I review Level 1 for high-risk code?
   - Did I find and resolve the issues?

2. Do the CI tests pass?
   - Unit tests
   - Integration tests
   - Linter and type checker

3. Are there unmitigated risks?
   - Is there security code without tests?
   - Is there business logic not verified against requirements?
   - Are there new dependencies not evaluated?

Typical time: 5-15 minutes.


When to "Trip the Breaker"

Signs that you should stop

"Trip the breaker" means stopping completely. You don't continue until you resolve the issue. These are the signs:

🛑 STOP IMMEDIATELY if:

1. The code does something you didn't ask for and you don't understand why
   → Claude Code sometimes "invents" features nobody asked for.
   → If you don't understand why something is there, don't accept it.

2. There's an import you don't recognize
   → It could be a hallucination (a library that doesn't exist).
   → It could be a dependency that introduces vulnerabilities.
   → Verify before continuing.

3. The security logic "looks off"
   → Your instinct detected something. Investigate.
   → Better to lose 15 minutes verifying than to lose 15 days
     responding to an incident.

4. The tests pass but don't test what they should
   → Passing tests doesn't mean correct code.
   → If the tests don't cover the risk scenarios, don't trust them.

5. The output is significantly different from what you expected
   → If you asked for a REST endpoint and it generated a WebSocket,
     something got lost in the communication.
   → Stop, review your prompt, regenerate.

The cost of NOT stopping

Scenario: Claude Code generates 3 files for a payment system.

Without a Circuit Breaker:
├── File 1: models.py → "Looks good" → Continue
├── File 2: payment_service.py → "Looks good" → Continue
├── File 3: routes.py → "Looks good" → Commit
├── 2 days later: integration test fails
├── Investigation: payment_service.py miscalculates the tax
├── But routes.py already uses payment_service's calculations
├── And other modules already depend on routes.py
└── Cost: 4 hours of debugging + refactor

With a Circuit Breaker:
├── File 1: models.py → Checkpoint → OK
├── File 2: payment_service.py → Checkpoint
│   └── "Are the tax calculations correct?" → NO
│   └── BREAKER TRIPPED → Fix before continuing
├── File 2 fixed → Checkpoint → OK
├── File 3: routes.py → Checkpoint → OK (uses correct calculations)
└── Cost: 15 minutes of review at the checkpoint

Circuit Breaker in Practice

Example 1: Generating multiple files

You ask Claude Code: "Generate an inventory module with models, service, and endpoints."

Checkpoint plan:

STEP 1: Claude Code generates models.py
└── CHECKPOINT:
    ├── Do the model fields make sense for inventory?
    ├── Are the types correct? (quantity as int, price as Decimal)
    ├── Are the relationships between models logical?
    └── → If OK, ask for the service

STEP 2: Claude Code generates inventory_service.py
└── CHECKPOINT:
    ├── Does it use the models generated in step 1?
    ├── Is the business logic correct?
    │   (Does it subtract stock correctly? Does it validate negative stock?)
    ├── Does it handle errors? (What happens if the product doesn't exist?)
    └── → If OK, ask for the endpoints

STEP 3: Claude Code generates routes.py
└── CHECKPOINT:
    ├── Do the endpoints use the step 2 service?
    ├── Are the input validations correct?
    ├── Are the status codes appropriate?
    ├── Is there auth where there should be?
    └── → If OK, integrate and prepare the commit

Example 2: Iterative generation with corrections

Sometimes the checkpoint leads you to fix and regenerate:

# STEP 1: Claude Code generates an inventory service

class InventoryService:
    def __init__(self, db: Session):
        self.db = db

    def reduce_stock(self, product_id: int, quantity: int) -> Product:
        product = self.db.query(Product).filter(
            Product.id == product_id
        ).first()

        if not product:
            raise ValueError("Product not found")

        product.stock -= quantity
        self.db.commit()
        return product

# CHECKPOINT 1: Review
# ⚠️ Doesn't validate that quantity is positive
# ⚠️ Doesn't validate that there's enough stock
# ⚠️ product.stock can go negative
# 🛑 BREAKER TRIPPED — incorrect business logic
# STEP 2: You fix it and ask it to regenerate with the corrections

# Prompt to Claude Code:
# "Fix reduce_stock so that it:
#  1. Validates that quantity > 0
#  2. Checks that there's enough stock
#  3. Uses select_for_update to avoid race conditions"

class InventoryService:
    def __init__(self, db: Session):
        self.db = db

    def reduce_stock(self, product_id: int, quantity: int) -> Product:
        if quantity <= 0:
            raise ValueError("Quantity must be positive")

        product = (
            self.db.query(Product)
            .filter(Product.id == product_id)
            .with_for_update()
            .first()
        )

        if not product:
            raise ValueError("Product not found")

        if product.stock < quantity:
            raise ValueError(
                f"Insufficient stock: {product.stock} available, "
                f"{quantity} requested"
            )

        product.stock -= quantity
        self.db.commit()
        self.db.refresh(product)
        return product

# CHECKPOINT 2: Review
# ✅ Validates quantity > 0
# ✅ Checks for enough stock
# ✅ Uses with_for_update() for race conditions
# ✅ Descriptive error message
# ✅ refresh() to return updated data
# → PASS — continue with the next file

Example 3: Checkpoint before commit

# You've integrated the code. Before commit:

# 1. Tests
$ pytest tests/test_inventory.py -v
# tests/test_inventory.py::test_reduce_stock_success PASSED
# tests/test_inventory.py::test_reduce_stock_insufficient PASSED
# tests/test_inventory.py::test_reduce_stock_negative_quantity PASSED
# tests/test_inventory.py::test_reduce_stock_not_found PASSED
# 4 passed in 0.3s
# → ✅ Tests pass

# 2. Linter
$ ruff check src/inventory/
# All checks passed!
# → ✅ Linter OK

# 3. Diff
$ git diff --stat
# src/inventory/models.py    | 25 +++++++
# src/inventory/service.py   | 48 ++++++++++++
# src/inventory/routes.py    | 62 ++++++++++++++++
# tests/test_inventory.py    | 85 ++++++++++++++++++++
# 4 files changed, 220 insertions(+)
# → ✅ Only the expected files

# → CHECKPOINT PASSED — commit

Checkpoint Templates

Template 1: Checkpoint per file

Use this template when Claude Code generates multiple files:

CHECKPOINT: [file name]
Date: [date]
MIT Level: [1/2/3]

□ Is it what I asked for?
□ Is the structure correct?
□ Are the imports real?
□ [If Level 1] Did I review every line of critical logic?
□ [If Level 1] Are the business values correct?
□ [If Level 2] Are the edge cases handled?
□ [If Level 2] Does the error handling exist?
□ [If Level 3] Does it look reasonable?

Result: PASS / FAIL / NEEDS EDIT
Notes: [observations]
Action: [continue / edit / regenerate / stop]

Template 2: Pre-commit checkpoint

PRE-COMMIT CHECKPOINT
Date: [date]

Tests:
□ pytest passes: [yes/no]
□ Tests cover risk scenarios: [yes/no]
□ Number of new tests: [number]

Quality:
□ Linter passes: [yes/no]
□ Type checker passes: [yes/no]

Diff:
□ Only expected files modified: [yes/no]
□ No sensitive files in the diff: [yes/no]
□ Diff reviewed manually: [yes/no]

Result: COMMIT / FIX AND RETRY / REVERT

Template 3: Pre-merge checkpoint

PRE-MERGE CHECKPOINT
Date: [date]
PR: [number/link]

Code Review:
□ Managing an Intern applied: [yes/no]
□ Level 1 reviewed exhaustively: [yes/no]
□ Issues found and resolved: [list]

CI:
□ Pipeline green: [yes/no]
□ Coverage didn't drop: [yes/no]

Risks:
□ Is there security code without tests? [yes/no]
□ Is there business logic not verified? [yes/no]
□ Are new dependencies evaluated? [yes/no]

Result: MERGE / ITERATE / BLOCK

Circuit Breaker in Different Workflows

Workflow 1: Fast generation (prototype)

When you're building a prototype, the checkpoints are lighter:

Prototype — light checkpoints:

Checkpoint 1 (After generating):
- Does it work? (compiles, responds, doesn't crash)
- Does the overall structure make sense?
- ⚡ 1-2 minutes per file

Checkpoint 2 (Before commit):
- Does the prototype demonstrate what I want?
- ⚡ 1 minute

Checkpoint 3 (Pre-merge):
- ❌ Doesn't apply in a prototype

Note: Light checkpoints are for PROTOTYPES.
When the code moves to production, apply
full checkpoints.

Workflow 2: Feature for production

For code going to production, the checkpoints are rigorous:

Production — rigorous checkpoints:

Checkpoint 1 (After generating):
- Apply the manager's 5 questions
- Classify into an MIT level
- Review according to the level
- ⏱️ 5-15 minutes per file

Checkpoint 2 (Integration):
- Does it integrate with the existing code?
- Do the tests pass with the new code?
- ⏱️ 5-10 minutes

Checkpoint 3 (Pre-commit):
- Full tests, linter, diff review
- ⏱️ 5-10 minutes

Checkpoint 4 (Pre-merge):
- Code review, CI pipeline, risk evaluation
- ⏱️ 10-20 minutes

Workflow 3: Debugging with Claude Code

When you use Claude Code for debugging, the checkpoints are different:

Debugging — validation checkpoints:

Checkpoint 1 (After a suggestion):
- Does the diagnosis make sense?
- Is the explanation of the bug plausible?
- ⏱️ 2-3 minutes

Checkpoint 2 (After the suggested fix):
- Does the fix resolve the bug?
- Does the fix introduce new bugs?
- Does the fix touch only what's necessary?
- ⏱️ 5-10 minutes

Checkpoint 3 (After applying):
- Is the original bug resolved?
- Do the regression tests pass?
- Are there no side effects?
- ⏱️ 5-10 minutes

Circuit Breaker Anti-Patterns

Anti-pattern 1: Checkpoints without criteria

❌ "I put a checkpoint every 10 lines of code"

→ Inefficient: you interrupt the flow constantly
→ Checkpoints aren't based on lines of code
→ They're based on logical units (files, functions, features)

Anti-pattern 2: Checkpoints that never "trip"

❌ "I always pass the checkpoint — I never stop anything"

→ If you never stop anything, you're not really verifying
→ Either your AI code is perfect (unlikely)
→ Or your checkpoints are too superficial
→ Review what you're verifying at each checkpoint

Anti-pattern 3: Checkpoints only at the end

❌ "I review everything at the end, before commit"

→ If the error is in the first file,
  you've already generated 4 files based on incorrect code
→ The cost of correction is exponentially higher
→ Early checkpoint = cheap correction

Anti-pattern 4: Breaker that never resets

❌ "Claude Code generated a bug once, now I review
    every import of every file forever"

→ The breaker should reset after resolving the issue
→ If the issue was specific (a fake import), it doesn't mean
  everything else is suspicious
→ Adjust your calibration, not your paranoia

Connection to the Project

How you'll use Circuit Breaker in Module 8

In the capstone project you'll receive a codebase with multiple files. Your review flow will use checkpoints:

  1. Checkpoint per module: You review each module of the codebase separately. You don't try to review everything at once.
  2. Checkpoint per type of issue: First you look for security issues (Red Zone). Then business logic. Then edge cases.
  3. Breaker if you find something serious: If a module has a serious security problem, you stop and document it before continuing with the next module.
  4. Final checkpoint: Before delivering, you verify that all issues are documented and that your review was complete.

Troubleshooting

Problem 1: "My checkpoints take too long"

Cause: You're verifying too much at each checkpoint. Solution: Combine it with Managing an Intern. In a Level 3 file checkpoint, you only do a visual review (30 seconds). In Level 1, you do invest 10-15 minutes. The average should be 3-5 minutes per checkpoint.

Problem 2: "I don't know when to 'trip the breaker'"

Cause: Lack of experience recognizing warning signs. Solution: Use the list of signs in this capsule. If you're not sure, stop anyway. It's better to stop unnecessarily (you lose 5 minutes) than not to stop when you should have (you lose hours or days).

Problem 3: "My team doesn't use checkpoints and they're doing fine"

Cause: "Doing fine" can mean they haven't had an incident yet, or that they aren't detecting the problems. Solution: Start applying checkpoints yourself. When your bug rate drops or you detect issues others don't, you'll have evidence to propose the process to the team.

Problem 4: "Claude Code generates everything at once and I can't do intermediate checkpoints"

Cause: You're asking for too much scope in a single prompt. Solution: Split your request. Instead of "generate the entire inventory module," ask: "generate the inventory models," review, and then "generate the service that uses those models." Each request is a natural checkpoint.


Exercises

Exercise 1: Define checkpoints (Easy)

Define the checkpoints for this flow: you ask Claude Code to generate a comment system for a blog.

Expected files:

  1. models.py — Comment models
  2. service.py — comment CRUD logic
  3. routes.py — REST endpoints
  4. moderation.py — filtering of inappropriate content
See solution
Checkpoint 1: After models.py (MIT Level: 3)
├── Does the model have the correct fields? (author, content, post_id, created_at)
├── Are the relationships with Post well defined?
├── Time: 1-2 minutes
└── Action: Continue if the fields make sense

Checkpoint 2: After service.py (MIT Level: 2)
├── Does it use the checkpoint 1 models?
├── Is the CRUD complete? (create, read, update, delete)
├── Does it check that the post exists before adding a comment?
├── Does it handle errors? (comment not found, post not found)
├── Time: 5-8 minutes
└── Action: Continue if the logic is correct

Checkpoint 3: After routes.py (MIT Level: 2)
├── Do the endpoints use the service?
├── Is there auth? (who can edit/delete comments?)
├── Are the status codes correct?
├── Time: 5-8 minutes
└── Action: Continue if the endpoints are correct

Checkpoint 4: After moderation.py (MIT Level: 1)
├── ⚠️ This file is Level 1: content filtering has
│   legal and UX implications
├── What criteria does it use for "inappropriate"?
├── Are there false positives that would censor legitimate content?
├── Can the filter be bypassed easily?
├── Time: 10-15 minutes
└── Action: Review exhaustively before continuing

Checkpoint 5: Pre-commit
├── Tests pass
├── Linter OK
├── Diff only has the 4 files + tests
└── Action: Commit

The key: moderation.py gets the most rigorous checkpoint because content filtering has real consequences (censoring legitimate content or allowing harmful content).

Exercise 2: Identify where to "trip" (Medium)

Claude Code generates these 3 files sequentially. In which one should you "trip the breaker"?

File 1: models.py

from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime

class OrderCreate(BaseModel):
    product_id: int
    quantity: int = Field(..., gt=0)
    shipping_address: str = Field(..., min_length=10)

class Order(OrderCreate):
    id: int
    total_price: float
    status: str = "pending"
    created_at: datetime

File 2: order_service.py

from models import Order, OrderCreate
from database import get_db

class OrderService:
    def create_order(self, order_data: OrderCreate) -> Order:
        db = get_db()
        product = db.get_product(order_data.product_id)
        total = product.price * order_data.quantity
        order = db.create_order(
            product_id=order_data.product_id,
            quantity=order_data.quantity,
            total_price=total,
        )
        return order

File 3: routes.py

from fastapi import APIRouter, Depends
from models import OrderCreate, Order
from order_service import OrderService

router = APIRouter(prefix="/orders", tags=["orders"])

@router.post("/", response_model=Order)
async def create_order(order: OrderCreate):
    service = OrderService()
    return service.create_order(order)

@router.get("/{order_id}", response_model=Order)
async def get_order(order_id: int):
    service = OrderService()
    return service.get_order(order_id)
See solution

File 1 (models.py): PASS with a minor observation.

  • total_price: float should be Decimal for money, but it's acceptable for a first pass.
  • Validations present (gt=0, min_length=10).
  • Observation: status: str = "pending" should be an Enum.
  • → Continue (it's not a reason to trip, they're improvements).

File 2 (order_service.py): TRIP THE BREAKER.

  • ⚠️ Doesn't check that the product exists (db.get_product can return None).
  • ⚠️ Doesn't check available stock. What happens if you order 100 units and there are 5?
  • ⚠️ There's no error handling. If get_product fails, the error rises with no context.
  • ⚠️ total = product.price * order_data.quantity — and the taxes? shipping? discounts?
  • ⚠️ There's no transaction. If create_order fails after calculating the total, it's left in an inconsistent state.
  • → STOP. Fix before generating routes.py, because routes.py will depend on this logic.

File 3 (routes.py): SHOULD NOT HAVE BEEN GENERATED YET.

  • If you had done a checkpoint on File 2, you would have stopped the generation.
  • Additionally: service = OrderService() is instantiated on every request (it doesn't use dependency injection). And the POST endpoint has no authentication.
  • → If it already exists, it needs to be regenerated after fixing File 2.

Lesson: The early checkpoint on File 2 would have avoided generating a File 3 based on incorrect logic.

Exercise 3: Design checkpoints for your project (Medium)

Think about a project you're working on (or a personal project). List 5 files or modules Claude Code could generate and define:

  1. The order of generation
  2. The checkpoint for each one
  3. The MIT level of each checkpoint
  4. What would make you "trip the breaker" in each one
See solution

There's no single answer — it depends on your project. Your checkpoint design should:

  • ✅ Generate first the files that others depend on (models before services before routes)
  • ✅ Have more rigorous checkpoints for security and business-logic files
  • ✅ Have light checkpoints for boilerplate and configuration
  • ✅ Define specific "trip" criteria for each file
  • ✅ Each checkpoint should list what to verify (not just "review")

Example for an e-commerce project:

OrderFileMIT LevelTrip if...Time
1models.py3Fields don't make sense for the domain2 min
2auth_service.py1Any security issue20 min
3product_service.py2Incorrect pricing logic8 min
4cart_service.py1Incorrect total calculations15 min
5routes.py2Endpoints without auth where there should be8 min

Exercise 4: Post-mortem with Circuit Breaker (Hard)

Read this scenario and answer: which checkpoints would have prevented the incident?

Scenario:
A developer uses Claude Code to generate an email
invitation system for a SaaS app.

Day 1: Generates models, service, routes. Accepts everything. Commit. Push.
Day 2: QA tests it and says "works fine."
Day 3: Deploy to production.
Day 5: A user reports that they can invite anyone
       to any team, not just theirs.
Day 5: Investigation reveals that the POST /invitations endpoint
       doesn't verify that the inviting user is a member of the
       team they're inviting to.
Day 5: 47 users have already been invited to incorrect teams.
Day 6: Hotfix, notification to affected users, post-mortem.
See solution

Checkpoints that would have prevented the incident:

Checkpoint 1 (After generating service.py): If the developer had applied the manager's 5 questions:

  • Question 3: "Is there anything an attacker could exploit?"
  • → "Does the service verify that the user belongs to the team?"
  • → Issue detected before generating routes.py

Checkpoint 2 (Before integrating routes.py): If the developer had verified the interfaces:

  • "Does the endpoint verify permissions?"
  • → A POST endpoint without permission verification is a breaker-trip sign

Checkpoint 3 (Before commit): If the developer had reviewed the diff with a security eye:

  • POST /invitations without Depends(verify_team_membership) → Red flag

Checkpoint 4 (Pre-merge / QA): QA tested "works fine" but didn't test the negative case:

  • "What happens if I try to invite to a team I'm not a member of?"
  • → If there were a QA checklist based on Circuit Breaker, this case would be included

Root cause: There was no security checkpoint at any point in the flow. The first real checkpoint was when a user reported the bug in production — 5 days and 47 users later.

Minimum checkpoints that would have sufficed:

  1. Checkpoint on service.py with the question: "does it verify permissions?" (Day 1)
  2. Pre-merge checkpoint with the criterion: "do endpoints that modify data have auth?" (Day 1)

Either of the two would have been enough.

Exercise 5: Quick vs complete checkpoint (Hard)

For each file generated by Claude Code, decide whether you apply a quick checkpoint (1-2 min) or a complete one (10+ min). Justify it.

  1. Dockerfile for a Python app
  2. auth/permissions.py with permission decorators by role
  3. utils/formatters.py with date and string formatting functions
  4. payments/stripe_integration.py with charging logic
  5. tests/test_models.py with 20 tests of Pydantic models
See solution
  1. Dockerfile → Quick checkpoint (1-2 min). Standard boilerplate. Verify: correct base image, doesn't copy secrets, multi-stage if applicable. Level 3.

  2. auth/permissions.py → Complete checkpoint (15-20 min). Critical security. Verify: each permission decorator works correctly, can't be bypassed, handles roles correctly, fails safe (deny by default). Level 1.

  3. utils/formatters.py → Quick checkpoint (1-2 min). Low-risk utilities. Verify: functions look correct, descriptive names. If they format financial data, move up to a medium checkpoint. Level 3.

  4. payments/stripe_integration.py → Complete checkpoint (20-30 min). Financial code + integration with an external service. Verify: API keys not hardcoded, correct amounts, idempotency keys, error handling for failed payments, validated webhooks. Level 1.

  5. tests/test_models.py → Medium checkpoint (5-8 min). Tests aren't production code, but incorrect tests give false confidence. Verify: that they test the right thing (not just that they pass), that they cover edge cases, that the assertions are meaningful. Level 2.


Summary

In this capsule you learned:

  • Circuit Breaker adapted from software engineering: you define checkpoints where you pause and verify before continuing
  • 4 types of checkpoints: after generating, before integrating, before commit, before merge
  • Each checkpoint has a different scope — you don't verify the same thing in all of them
  • "Trip the breaker" when: code does something you didn't ask for, unknown imports, suspicious security logic, tests that don't test the right thing
  • The cost of not stopping is exponentially higher than the cost of stopping early
  • Checkpoint templates give you a reproducible process
  • Checkpoints combine with Managing an Intern: the MIT level determines the depth of the checkpoint

Next capsule: Trust Calibration — how much to trust by type of task, with a table you can use tomorrow.


Additional resources

  1. Circuit Breaker Pattern — Martin Fowler - The original pattern adapted to code review
  2. Google — Code Review Speed - How Google balances speed and rigor in code review
  3. Conventional Commits - A commit structure that facilitates checkpoints
  4. Ship / Show / Ask — Rouan Wilsenach - A framework for when you need review and when you don't
  5. Anthropic — Claude Code Documentation - Official Claude Code documentation
  6. The Checklist Manifesto — Atul Gawande - Why checklists save lives (and code)

Debugging & Code Review with Claude Code — Module 2, Capsule 03 Claude Code Agentic Development Path — Guide #6 of 11