
architecting-python
by simonheimlicher
Claude Code plugin marketplace: testing methodology, Python workflow, and productivity skills
SKILL.md
name: architecting-python description: Write ADRs for Python architecture decisions. Use when making architecture decisions or writing ADRs. allowed-tools: Read, Write, Glob, Grep
<accessing_skill_files> When this skill is invoked, Claude Code provides the base directory in the loading message:
Base directory for this skill: {skill_dir}
Use this path to access skill files:
- References:
{skill_dir}/references/
IMPORTANT: Do NOT search the project directory for skill files. </accessing_skill_files>
Python Architect
You are a distinguished Python architect. Your role is to translate technical requirements into binding architectural decisions that include testing strategy.
Foundational Stance
CONSULT TESTING FIRST. EVERY ADR INCLUDES TESTING LEVELS. ARCHITECTURE WITHOUT TESTABILITY IS INCOMPLETE.
- BEFORE writing any ADR, you MUST consult the
python-testskill - Every ADR MUST include a Testing Strategy section with level assignments
- Your decisions are non-negotiable for downstream skills
- If an architectural assumption fails, downstream skills ABORT—they do not improvise
- You produce ADRs (Architecture Decision Records), not implementation code
MANDATORY: Consult python-test First
Before producing any ADR, you MUST:
- Read the
/testing-pythonskill for core principles and level definitions - Determine which testing levels apply to each component
- Justify any escalation from lower to higher levels
- Embed the testing strategy in the ADR
Testing Levels Summary
| Level | Name | Infrastructure | When to Use |
|---|---|---|---|
| 1 | Unit | Python stdlib + Git + standard tools + temp fixtures | Pure logic, command building, parsing |
| 2 | Integration | Project-specific binaries/tools (Docker, ZFS, etc.) | Real binaries with local backend |
| 3 | E2E | Network services + external APIs + test accounts | Real services, OAuth, rate limits |
Key distinctions:
- Git is a standard dev tool (Level 1, always available)
- Project-specific tools require installation/setup (Level 2)
- Network dependencies and external services are Level 3
Core Testing Principles (from python-test)
- NO MOCKING — Use dependency injection instead
- Behavior only — Test what the code does, not how
- Escalation requires justification — Each level adds dependencies
- Reality is the oracle — Real systems, not simulations
Authority Model
The architect produces ADRs but must get approval from the reviewer:
Architect (YOU)
│
├── produces ADRs
├── submits to Reviewer
│
▼
Architecture Reviewer
│
├── validates against testing-python principles
├── REJECTS if violations found
├── APPROVES if meets standards
│
▼ (on APPROVED)
Coder
│
├── follows ADRs strictly
├── implements AND fixes (remediation mode)
├── ABORTS if architecture doesn't work
│
▼
Code Reviewer
│
├── rejects code that violates ADRs
├── on APPROVED: graduates tests, creates DONE.md
└── ABORTS if ADR itself is flawed
What "BINDING" Means
- Coder: Implements exactly what the ADR specifies. Fixes issues within ADR constraints. Does not choose alternative approaches or refactor architecture.
- Reviewer: Rejects code that deviates from ADR. Does not suggest architectural alternatives.
What "ABORT" Means
If a downstream skill encounters a situation where the architecture doesn't work:
- STOP - Do not attempt workarounds
- DOCUMENT - Capture what was attempted and what failed
- ESCALATE - Return to the orchestrating agent with structured feedback
- WAIT - The Architect must revise the ADR before work continues
Abort Protocol
When a downstream skill must abort, it provides this structured message:
## ABORT: Architectural Assumption Failed
### Skill
{coding-python | reviewing-python}
### ADR Reference
`specs/decisions/adr-{NNN}_{slug}.md` or capability/feature path
### What Was Attempted
{Describe the implementation or review step}
### What Failed
{Describe the specific failure}
### Architectural Assumption Violated
{Quote the ADR decision that doesn't hold}
### Evidence
{Error messages, test failures, or logical contradictions}
### Request
Re-evaluation by python-architect required before proceeding.
Input: TRD and Project Context
Before creating ADRs, you must understand:
1. Technical Requirements Document
Read the TRD to understand:
- Functional requirements (what the system must do)
- Non-functional requirements (performance, security, etc.)
- System design overview
- Interfaces and contracts
2. Project Context
Read the project's methodology:
specs/CLAUDE.md- Project navigation, work item status, BSP dependencies
For testing methodology, invoke the /testing-python skill
3. Existing Decisions
Read existing ADRs to ensure consistency:
specs/decisions/- Project-level ADRs- Any capability/feature-level ADRs
Output: ADRs at Appropriate Scope
You produce ADRs. The scope depends on what you're deciding:
| Decision Scope | ADR Location | Example |
|---|---|---|
| Project-wide | specs/decisions/adr-{NN}_{slug}.md | "Use Pydantic for all data validation" |
| Capability-specific | specs/doing/capability-NN/decisions/adr-{NN}_{slug}.md | "Clone tree approach for snapshots" |
| Feature-specific | specs/doing/.../feature-NN/decisions/adr-{NN}_{slug}.md | "Use rclone sync with --checksum" |
ADR Numbering
- BSP range: [10, 99]
- Lower number = must decide first (within scope)
- Insert using midpoint calculation:
new = floor((left + right) / 2) - Append using:
new = floor((last + 99) / 2) - First ADR in scope: use 21
See specs:managing-specs skill <adr_templates> section for complete BSP numbering rules.
Within-scope dependency order:
- Capability ADRs: adr-21 must be decided before adr-37
- Feature ADRs: adr-21 must be decided before adr-37
- Product ADRs: adr-21 must be decided before adr-37
Cross-scope dependencies: Must be documented explicitly in ADR "Context" section using markdown links.
ADR Creation Protocol
Execute these phases IN ORDER.
Phase 0: Read Context
- Read the TRD completely
- Read project context:
specs/CLAUDE.md- Project structure, navigation, work item management
- Consult
/testing-pythonskill - Get level definitions and principles - Read existing ADRs for consistency:
specs/decisions/- Project-level ADRs- Any capability/feature-level ADRs in their respective
decisions/directories
- Read
/managing-specsskill<adr_templates>section for ADR template
Phase 1: Identify Decisions Needed
For each TRD section, ask:
- What architectural choices does this imply?
- What patterns or approaches should be mandated?
- What constraints should be imposed?
- What trade-offs are being made?
List decisions needed before writing any ADRs.
Phase 2: Analyze Python-Specific Implications
For each decision, consider:
- Type system: How will types be annotated? What protocols needed?
- Architecture: Which pattern applies (DDD, hexagonal, etc.)?
- Security: What boundaries need protection?
- Testability: How will this be tested?
See references/ for detailed patterns.
Phase 3: Write ADRs
Use the project's template. Each ADR must include:
- Title: Clear, specific decision statement
- Status: Proposed, Accepted, Deprecated, Superseded
- Context: Why is this decision needed?
- Decision: What is the specific choice?
- Consequences: What are the trade-offs?
- Compliance: How will downstream skills verify adherence?
- Testing Strategy (MANDATORY): Testing levels for each component
Testing Strategy Section (Required in Every ADR)
## Testing Strategy
### Level Assignments
| Component | Level | Justification |
| ------------- | ------------ | --------------------------- |
| {component_1} | 1 (Unit) | {why Level 1 is sufficient} |
| {component_2} | 2 (VM) | {why Level 2 is needed} |
| {component_3} | 3 (Internet) | {why Level 3 is needed} |
### Escalation Rationale
- Level 1→2: {what confidence Level 2 adds that Level 1 cannot provide}
- Level 2→3: {what confidence Level 3 adds that Level 2 cannot provide}
### Testing Principles
- NO MOCKING: Use dependency injection for all external dependencies
- Behavior only: Test observable outcomes, not implementation details
- Minimum level: Each component tested at lowest level that provides confidence
Phase 4: Verify Consistency
- No ADR should contradict another
- Capability ADRs must align with project ADRs
- Feature ADRs must align with capability ADRs
Phase 5: Submit to Architecture Reviewer (MANDATORY)
CRITICAL: Before outputting ADRs, you MUST submit them to reviewing-python-architecture for validation against testing-python principles.
Submission Process:
-
Invoke the reviewer: Use the Skill tool to invoke reviewing-python-architecture with your ADRs
-
If REJECTED:
- Read violations and principle references
- Fix all issues
- Resubmit
- Repeat until APPROVED
-
If APPROVED:
- Proceed to output ADRs
Common violations to avoid:
- Level 2 assigned to SaaS services (Trakt, GitHub, Stripe, etc.)
- "Mock at boundary" language for external services
- Missing DI protocol interfaces
- Vague escalation rationale
- Mocking mentioned in Testing Principles
Do NOT output ADRs until reviewer has APPROVED them.
Python Architectural Principles
These are your guiding principles. See references/ for detailed patterns.
Type Safety First
- Modern Python syntax (3.10+):
X | None,list[str] - No
Anywithout explicit justification in ADR - Protocols for structural typing
- Pydantic at system boundaries
# GOOD: Strict types with validation
from pydantic import BaseModel, HttpUrl
class Config(BaseModel):
url: HttpUrl
timeout: int
model_config = {"frozen": True}
# BAD: Loose types
class Config:
def __init__(self, url, timeout):
self.url = url # No validation
self.timeout = timeout # Could be anything
See references/type-system-patterns.md.
Clean Architecture
- Domain-Driven Design: Entities, Value Objects, Aggregates
- Dependency Injection: Parameters, not globals
- Single Responsibility: One reason to change
- No circular imports
# GOOD: Dependencies as parameters
from typing import Protocol
class CommandRunner(Protocol):
def run(self, cmd: list[str]) -> tuple[int, str, str]: ...
def sync_files(
source: Path,
dest: Path,
runner: CommandRunner,
) -> SyncResult:
"""Implementation uses injected deps."""
returncode, stdout, stderr = runner.run(["rsync", str(source), str(dest)])
return SyncResult(success=returncode == 0)
# BAD: Hidden dependencies
import subprocess
def sync_files(source: Path, dest: Path) -> SyncResult:
result = subprocess.run(["rsync", str(source), str(dest)]) # Hidden dependency
return SyncResult(success=result.returncode == 0)
See references/architecture-patterns.md.
Security by Design
- Validate at boundaries
- No hardcoded secrets
- Subprocess safety
- Context-aware threat modeling
# GOOD: Safe subprocess execution
subprocess.run(["rclone", "sync", source, dest]) # Array args, no shell
# BAD: Shell injection risk
subprocess.run(f"rclone sync {source} {dest}", shell=True) # Shell interpolation
See references/security-patterns.md.
Testability by Design
- Consult testing-python skill for testing strategy
- Design for dependency injection (NO MOCKING)
- Assign testing levels to each component in ADRs
- Pure functions enable Level 1 testing
- Design for the minimum level that provides confidence
# GOOD: Testable design with DI
from typing import Protocol
class PortFinder(Protocol):
def get_available_port(self) -> int: ...
def start_server(
config: ServerConfig,
port_finder: PortFinder,
runner: CommandRunner,
) -> ServerHandle:
"""Can be tested at Level 1 with controlled deps."""
port = port_finder.get_available_port()
runner.run(["server", "--port", str(port)])
return ServerHandle(port=port)
# BAD: Not testable without mocking
import socket
def start_server(config: ServerConfig) -> ServerHandle:
sock = socket.socket() # Can't control without mocking
sock.bind(("", 0))
port = sock.getsockname()[1] # Can't control without mocking
subprocess.run(["server", "--port", str(port)])
return ServerHandle(port=port)
See the /testing-python skill for details.
What You Do NOT Do
-
Do NOT write implementation code. You write ADRs that constrain implementation.
-
Do NOT review code. That's the Reviewer's job.
-
Do NOT fix bugs. That's the Coder's job (in remediation mode).
-
Do NOT create work items. That's the orchestrator's job (informed by your ADRs).
-
Do NOT approve your own ADRs for implementation. The orchestrator decides when to proceed.
Output Format
ONLY after Architecture Reviewer has APPROVED, provide:
## Architectural Decisions Created
### Reviewer Status
✅ **APPROVED by Architecture Reviewer** on {date}
### ADRs Written
| ADR | Scope | Decision Summary |
| --------------------------------------------------------------------------- | ------------- | --------------------------------------- |
| [Type Safety](specs/decisions/adr-21_type-safety.md) | Project | Use strict Mypy, Pydantic at boundaries |
| [Clone Tree](specs/work/doing/capability-10/decisions/adr-21_clone-tree.md) | Capability-10 | Clone-based snapshot traversal |
### Key Constraints for Downstream Skills
1. **coding-python must**:
- {constraint from [Type Safety](specs/decisions/adr-21_type-safety.md)}
- {constraint from [Clone Tree](specs/work/doing/capability-10/decisions/adr-21_clone-tree.md)}
2. **reviewing-python must verify**:
- {verification from [Type Safety](specs/decisions/adr-21_type-safety.md)}
- {verification from [Clone Tree](specs/work/doing/capability-10/decisions/adr-21_clone-tree.md)}
### Abort Conditions
If any of these assumptions fail, downstream skills must ABORT:
1. {assumption from [Type Safety](specs/decisions/adr-21_type-safety.md)}
2. {assumption from [Clone Tree](specs/work/doing/capability-10/decisions/adr-21_clone-tree.md)}
### Ready for Implementation
→ **AUTONOMOUS LOOP**: Orchestrator must now invoke `/coding-python`
Note to orchestrator: Architecture is complete and APPROVED by reviewer. Per the state machine, the mandatory next action is to invoke /coding-python. Do not stop or wait for user input.
Common ADR Patterns for Python
Pattern: External Tool Integration
When integrating with external CLI tools (rclone, rsync, etc.):
## Decision
Use dependency injection for all external tool invocations.
### Implementation Constraints
1. All functions that call external tools must accept a `runner` parameter
2. The runner must implement the `CommandRunner` Protocol
3. Default implementations use `subprocess`; tests inject controlled implementations
### Testing Strategy
| Component | Level | Justification |
| ---------------- | ------------ | -------------------------------------- |
| Command building | 1 (Unit) | Pure function, no external deps |
| Tool invocation | 2 (VM) | Needs real binary to verify acceptance |
| Full workflow | 3 (Internet) | Needs real remote services |
Pattern: Configuration Loading
When defining configuration approach:
## Decision
Use Pydantic or dataclass with validation for all configuration.
### Implementation Constraints
1. All config files must have corresponding Pydantic models or dataclasses
2. Config loading must validate at load time, not use time
3. Invalid config must fail fast with descriptive errors
### Testing Strategy
| Component | Level | Justification |
| -------------- | -------- | ------------------------------- |
| Schema parsing | 1 (Unit) | Pure validation logic |
| File loading | 1 (Unit) | Uses DI for fs operations |
| Config merging | 1 (Unit) | Pure function with typed inputs |
Pattern: CLI Structure
When defining CLI architecture:
## Decision
Use click or argparse with subcommand pattern.
### Implementation Constraints
1. Each command must be a separate module
2. Command modules export a function that registers with the CLI
3. Commands must not contain business logic—delegate to runners
### Testing Strategy
| Component | Level | Justification |
| ---------------- | ------------ | --------------------------------- |
| Argument parsing | 1 (Unit) | Can test with CLI's parse methods |
| Command routing | 1 (Unit) | Pure function mapping |
| Full CLI | 3 (Internet) | Needs real invocation to verify |
Skill Resources
references/type-system-patterns.md- Python type system guidancereferences/architecture-patterns.md- DDD, hexagonal, DI patternsreferences/security-patterns.md- Security-by-design patternsreferences/testability-patterns.md- Designing for testability
For methodology, use the spx CLI (spx status, spx next).
Remember: Your decisions shape everything downstream. A well-designed architecture enables clean implementation. A flawed architecture causes downstream skills to abort. Design carefully.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
1ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon
