---
name: reviewing-python-architecture
description: Review ADRs to check they follow testing principles and parent PDR constraints. Use when reviewing ADRs or architecture decisions.
allowed-tools: Read, Grep
---
Review ADRs against `/testing` principles and applicable PDR constraints. Point out violations, reference the specific principle, and show correct architecture.
1. Read `/testing` for methodology (5 stages, 5 factors, 7 exceptions)
2. Identify violations of testing principles and parent PDR constraints
3. Output APPROVED or REJECTED with specific violations
4. Show correct approach with code examples
From `/testing`:
**Level definitions** (from Stage 2 Five Factors):
- **Level 1**: Pure computation, file I/O with temp dirs, standard dev tools (git, curl)
- Test directly, no doubles needed
- **Level 2**: Real dependencies via harnesses (Docker, databases, project-specific binaries)
- Use real systems, not fakes
- **Level 3**: Real credentials, external services, browsers
- Full real-world workflows
**Critical rules** (from Five Factors):
- Standard dev tools (git, cat, grep, curl) are Level 1
- Project-specific tools (Docker, PostgreSQL, Hugo) are Level 2
- SaaS services (Trakt, GitHub API, Stripe, Auth0) jump from Level 1 → Level 3 (no Level 2)
- Network dependencies and external services are Level 3
**Mocking prohibition** (Cardinal Rule):
- **NO mocking. Ever.** - `/testing` cardinal rule
- NO `unittest.mock.patch` for external services
- NO `respx.mock` for internet APIs
- Use dependency injection with Protocol interfaces instead
- Test doubles (stubs, spies, fakes) only when exception case applies
**Reality principle**:
- "Reality is the oracle" - tests must verify behavior against real systems
- A fake proves your code works with your imagination, not the real system
**Test doubles require exception case** (Stage 5):
- Only 7 legitimate exceptions for test doubles
- Each use must document which exception applies
- No exception = no doubles, test at Level 2
````markdown
# ARCHITECTURE REVIEW
**Decision:** [APPROVED | REJECTED]
---
## Violations
### {Violation name}
**Where:** Lines {X-Y}
**Principle violated:** /testing {section name}
**Why this fails:** {Direct explanation}
**Correct approach:**
```{language}
{Show what the architecture should be}
```
````
---
{Repeat for each violation}
---
## Required Changes
{Concise list of what must change}
---
## References
- /testing: {section name} (principle violated)
- /standardizing-python-testing: {section if applicable}
---
{If REJECTED: "Revise and resubmit"}
{If APPROVED: "Architecture meets standards"}
````
**Don't:**
- Reference specific line numbers (they change)
- Provide grep commands
- Explain multiple times
- Count statistics
**Do:**
- Reference `/testing` section names (e.g., "Stage 5 Exception 1", "Cardinal Rule")
- Show correct architecture with code examples
- Be direct about violations
- Reference `/standardizing-python-testing` for Python-specific patterns
```markdown
# ARCHITECTURE REVIEW
**Decision:** REJECTED
---
## Violations
### Level 2 Assigned to SaaS Service
**Where:** Lines 132-133
**Principle violated:** /testing Stage 2 Factor 2
Trakt.tv is a SaaS service that cannot run locally. Per /testing Five Factors:
- SaaS services have no Level 2 - jump from Level 1 to Level 3
**Correct approach:**
```markdown
| List operations | 1 | DI with TraktListProvider protocol |
| List operations | 3 | Real Trakt API with test account |
````
---
### Mocking External Services
**Where:** Lines 132, 133, 145
**Principle violated:** /testing Cardinal Rule
Testing Strategy says "Mock at the PyTrakt API boundary" - this violates the NO MOCKING principle.
**Correct approach:**
Use dependency injection per /standardizing-python-testing:
```python
class TraktListProvider(Protocol):
def __call__(self, list_name: str, username: str) -> Any | None: ...
# Level 1: Inject fake implementation (Exception 1: Failure modes)
# Level 3: Use real PyTrakt
```
---
## Required Changes
1. Remove all Level 2 assignments for SaaS operations
2. Remove "Mock at boundary" language
3. Add DI protocol definitions per /standardizing-python-testing
4. Document which exception case justifies any test doubles
---
## References
- /testing: Cardinal Rule (no mocking)
- /testing: Stage 2 Factor 2 (dependency levels)
- /testing: Stage 5 (exception cases for test doubles)
- /standardizing-python-testing: Protocol patterns
---
Revise and resubmit.
```
Review is complete when:
- [ ] Checked for mocking violations (Cardinal Rule)
- [ ] Verified level assignments match `/testing` Five Factors
- [ ] Checked test double usage has documented exception case
- [ ] Output follows format with section references (not line numbers)
- [ ] Correct approach shown with code examples
```