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:
- Checkpoint per module: You review each module of the codebase separately. You don't try to review everything at once.
- Checkpoint per type of issue: First you look for security issues (Red Zone). Then business logic. Then edge cases.
- 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.
- 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:
models.py— Comment modelsservice.py— comment CRUD logicroutes.py— REST endpointsmoderation.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: floatshould beDecimalfor 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_productcan 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_productfails, the error rises with no context. - ⚠️
total = product.price * order_data.quantity— and the taxes? shipping? discounts? - ⚠️ There's no transaction. If
create_orderfails 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:
- The order of generation
- The checkpoint for each one
- The MIT level of each checkpoint
- 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:
| Order | File | MIT Level | Trip if... | Time |
|---|---|---|---|---|
| 1 | models.py | 3 | Fields don't make sense for the domain | 2 min |
| 2 | auth_service.py | 1 | Any security issue | 20 min |
| 3 | product_service.py | 2 | Incorrect pricing logic | 8 min |
| 4 | cart_service.py | 1 | Incorrect total calculations | 15 min |
| 5 | routes.py | 2 | Endpoints without auth where there should be | 8 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:
- Checkpoint on service.py with the question: "does it verify permissions?" (Day 1)
- 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.
Dockerfilefor a Python appauth/permissions.pywith permission decorators by roleutils/formatters.pywith date and string formatting functionspayments/stripe_integration.pywith charging logictests/test_models.pywith 20 tests of Pydantic models
See solution
-
Dockerfile → Quick checkpoint (1-2 min). Standard boilerplate. Verify: correct base image, doesn't copy secrets, multi-stage if applicable. Level 3.
-
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.
-
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.
-
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.
-
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
- Circuit Breaker Pattern — Martin Fowler - The original pattern adapted to code review
- Google — Code Review Speed - How Google balances speed and rigor in code review
- Conventional Commits - A commit structure that facilitates checkpoints
- Ship / Show / Ask — Rouan Wilsenach - A framework for when you need review and when you don't
- Anthropic — Claude Code Documentation - Official Claude Code documentation
- 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