Files
ai-development-scaffold/.claude/CLAUDE.md
James Bland a32828facd fix: make refactor-scan step mandatory in TDD workflow
- Changed REFACTOR step from optional to MANDATORY
- Added explicit Claude Code instructions requiring refactor-scan after every GREEN
- Split Quality Gates into "After Every GREEN" and "Before Every PR"
- Added clear process: commit → refactor-scan → apply → commit separately

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:12:20 -05:00

7.7 KiB

Development Standards

Core Philosophy

TDD is non-negotiable. Every line of production code must be written in response to a failing test. No exceptions.

Model Strategy: Use opusplan - Opus for planning/architecture, Sonnet for code execution.

Quick Reference

Languages & Tools

Language Test Framework Linter Formatter
Python pytest + pytest-asyncio Ruff Ruff
TypeScript Vitest ESLint ESLint
Rust cargo test clippy rustfmt
Terraform terraform validate tflint terraform fmt

Commands by Language

# Python
pytest                          # Run tests
pytest --cov=src --cov-report=term-missing  # With coverage
ruff check . && ruff format .   # Lint and format

# TypeScript
npm test                        # Vitest
npm run lint                    # ESLint
npm run typecheck               # tsc --noEmit

# Rust
cargo test                      # Run tests
cargo clippy -- -D warnings     # Lint (deny warnings)
cargo fmt --check               # Check formatting

# Terraform
terraform validate              # Validate
terraform fmt -check -recursive # Check formatting
terraform plan                  # Preview changes

TDD Workflow (RED-GREEN-REFACTOR)

1. RED: Write a Failing Test

  • Write test first that fails for the right reason
  • NO production code until test fails

2. GREEN: Make It Pass

  • Write MINIMUM code to pass the test
  • No "while you're there" additions

3. REFACTOR: Mandatory Quality Assessment

CRITICAL: This step is MANDATORY after every GREEN, not optional.

Process:

  1. Commit immediately after tests pass (before any refactoring)

    git add . && git commit -m "feat: implement X"
    
  2. Invoke refactor-scan agent - THIS IS NOT OPTIONAL

    • Use @refactor-scan to assess the code
    • This happens AUTOMATICALLY after every successful test pass
    • The agent identifies refactoring opportunities
  3. Apply refactoring if recommended

    • Make improvements identified by the scan
    • Ensure all tests still pass
    • Commit refactoring separately:
    git commit -m "refactor: improve X based on scan"
    

Claude Code Instructions (MANDATORY)

After every successful test pass (GREEN state), you MUST:

  1. Commit the working code immediately
  2. Proactively invoke the @refactor-scan agent (or use Task tool with subagent_type: refactor-scan)
  3. NOT proceed to the next feature/test until refactor assessment is complete
  4. Apply recommended refactoring and commit separately

This is not optional. Treat refactor-scan invocation with the same priority as running tests.

Coverage Requirements

Layer Target Notes
Domain/Business Logic 90%+ Critical path
API Routes 80%+ Validation paths
Infrastructure/DB 70%+ Integration points
UI Components 80%+ Behavior testing

Exceptions (document in code):

  • Generated code (migrations, types)
  • Third-party thin wrappers
  • Debug utilities

Type Safety

Python

  • Pydantic v2 for validation at boundaries
  • Type hints on all public functions
  • mypy --strict compliance

TypeScript

  • Strict mode always ("strict": true)
  • No any types - use unknown if truly unknown
  • Zod schemas at trust boundaries
  • type for data, interface for behavior contracts only

Rust

  • Leverage the type system fully
  • Use Result<T, E> for fallible operations
  • Prefer thiserror for error types

Testing Principles

Test Behavior, Not Implementation

// BAD - tests implementation
it('should call validateAmount', () => {
  const spy = jest.spyOn(validator, 'validateAmount');
  processPayment(payment);
  expect(spy).toHaveBeenCalled();
});

// GOOD - tests behavior
it('should reject negative amounts', () => {
  const payment = getMockPayment({ amount: -100 });
  const result = processPayment(payment);
  expect(result.success).toBe(false);
});

Factory Functions (No let/beforeEach)

const getMockPayment = (overrides?: Partial<Payment>): Payment => ({
  amount: 100,
  currency: 'GBP',
  ...overrides,
});

Security (Zero Tolerance)

  • NEVER hardcode secrets, passwords, API keys
  • NEVER commit .env files with real values
  • Use AWS Secrets Manager or environment variables
  • Validate ALL user input at boundaries
  • Parameterized queries only (no string concatenation)

Code Style

  • Immutable by default - no mutations
  • Pure functions where possible
  • Early returns over nested conditionals
  • Options objects for 3+ parameters
  • No comments - code should be self-documenting
  • DRY (Don't Repeat Knowledge) - eliminate duplicate business logic, but don't abstract merely similar code

DRY Clarification

DRY means don't duplicate knowledge, not code. Structural similarity is fine.

// NOT duplication - different business rules
const validatePaymentLimit = (amount: number) => amount <= 10000;
const validateTransferLimit = (amount: number) => amount <= 10000;
// These will evolve independently - keep separate

// IS duplication - same business rule in multiple places
// BAD: FREE_SHIPPING_THRESHOLD defined in 3 files
// GOOD: Single constant imported where needed

"Duplicate code is far cheaper than the wrong abstraction."

Monorepo Patterns

project/
├── apps/
│   ├── backend/          # Python FastAPI
│   └── frontend/         # React TypeScript
├── packages/
│   └── shared/           # Shared types/utils
├── infrastructure/
│   ├── terraform/        # IaC
│   └── ansible/          # Config management
└── tests/
    ├── backend/
    └── frontend/

Git Workflow

  • Conventional commits: feat:, fix:, refactor:, test:, docs:
  • One logical change per commit
  • Tests and implementation in same commit
  • PR must pass all checks before merge

Chrome/Browser Testing

For quick verification during development:

  1. Use Claude's Chrome MCP tools for rapid testing
  2. Take screenshots to verify UI state
  3. Record GIFs for complex interactions

For CI/permanent tests:

  1. Write Playwright tests for E2E flows
  2. Use React Testing Library for component behavior
  3. Test accessibility with axe-core

When to Use Which Model

Opus (via plan mode or explicit switch):

  • Architecture decisions
  • Complex debugging
  • Code review
  • Multi-file refactoring plans

Sonnet (default execution):

  • Writing code
  • Running tests
  • Simple fixes
  • File operations

Skills (Auto-Loaded)

Skills are automatically loaded when relevant context is detected. Available skills:

Languages: Python, TypeScript, Rust, Go, Java, C#

Infrastructure: AWS, Azure, GCP, Terraform, Ansible, Docker/Kubernetes, Database/Migrations, CI/CD

Testing: TDD workflow, UI Testing, Browser Testing (Playwright + Chrome MCP)

Patterns: Monorepo, API Design, Observability (logging, metrics, tracing)

Agents (Invoke with @)

  • @tdd-guardian - TDD enforcement and guidance
  • @code-reviewer - Comprehensive PR review
  • @security-scanner - Vulnerability detection
  • @refactor-scan - Refactoring assessment (TDD step 3)
  • @dependency-audit - Package security/updates

Quality Gates

After Every GREEN (Before Next RED)

  • Tests pass (GREEN achieved)
  • Code committed (preserve working state)
  • refactor-scan agent executed (MANDATORY)
  • Refactoring applied (if recommended)
  • Tests still pass (after refactoring)
  • Separate refactor commit created (if changes made)

Before Every PR/Push

  • All tests pass
  • Coverage meets threshold (80%+)
  • No linting errors
  • Type checking passes
  • No secrets in code
  • TDD compliance verified