Files
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

264 lines
7.7 KiB
Markdown

# 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
```bash
# 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)
```bash
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:
```bash
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
```typescript
// 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`)
```typescript
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.
```typescript
// 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