/sc:principles - Code Principles Validator
Mandatory validation skill enforcing four fundamental software engineering principles:
- KISS (Keep It Simple, Stupid) - Code should be as simple as possible
- Functional Core, Imperative Shell - Business logic must be pure; I/O belongs at edges
- SOLID - Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, Dependency Inversion
- Let It Crash - Fail fast for bugs; handle errors explicitly at boundaries
Quick Start
bash
# Full validation (all four principles)
/sc:principles src/
# KISS only validation
/sc:principles src/ --kiss-only
# Purity only validation
/sc:principles src/ --purity-only
# SOLID only validation
/sc:principles src/ --solid-only
# Let It Crash only validation
/sc:principles src/ --crash-only
# Strict mode (warnings become errors)
/sc:principles src/ --strict
# Generate detailed report
/sc:principles src/ --report
Behavioral Flow
1. INITIALIZE
├── Detect scope root
├── Find changed Python files (git diff)
└── Determine file contexts (core vs shell)
2. ANALYZE
├── Parse AST for each file
├── Calculate complexity metrics (KISS)
├── Detect I/O patterns (Purity)
├── Check structural patterns (SOLID)
└── Analyze error handling (Let It Crash)
3. VALIDATE
├── Compare against thresholds
├── Classify violations (error vs warning)
└── Apply context rules (core stricter than shell)
4. REPORT/BLOCK
├── Output violations with locations
├── Generate actionable recommendations
└── Exit 0 (pass) or 2 (blocked)
Validation Rules
KISS Gate
| Metric | Threshold | Severity | Description |
|---|
| Cyclomatic Complexity | > 10 | error | Number of independent paths through code |
| Cyclomatic Complexity | > 7 | warning | Early warning for growing complexity |
| Cognitive Complexity | > 15 | error | Weighted complexity (nested structures count more) |
| Function Length | > 50 lines | error | Lines of code per function (inclusive count) |
| Nesting Depth | > 4 levels | error | If/for/while/with/try nesting |
| Parameter Count | > 5 | warning | Function parameters |
Cognitive vs Cyclomatic Complexity:
- Cyclomatic counts decision points (branches)
- Cognitive weights nested structures more heavily: per control structure
- Example: has low cyclomatic but high cognitive (hard to read)
Purity Gate
The "Functional Core, Imperative Shell" pattern:
| Layer | Path Patterns | I/O Allowed | Severity |
|---|
| Core | , , , , | NO | error |
| Shell | , , , , , | YES | warning |
Note: Files in
,
,
,
,
, and
are treated as shell (I/O allowed).
Detected I/O Patterns:
| Category | Examples |
|---|
| File I/O | , , , |
| Network | , , , |
| Database | , , , |
| Subprocess | , , |
| Global State | , keywords |
| Side Effects | , , |
| Async I/O | , , , |
SOLID Gate
Detects structural violations of SOLID design principles.
| Principle | Detection | Severity | Description |
|---|
| SRP | File >300 lines, class with >5 public methods | warning | Single Responsibility - one reason to change |
| OCP | chains on type, cascades | warning | Open-Closed - extend, don't modify |
| LSP | Override that raises | error | Liskov Substitution - honor contracts |
| ISP | Interface/protocol with >7 methods | warning | Interface Segregation - small interfaces |
| DIP | Direct instantiation in business logic | warning | Dependency Inversion - depend on abstractions |
Code Smells to Flag:
| Smell | Principle | Recommended Fix |
|---|
| File >300 lines | SRP | Extract responsibilities into modules |
| if/else type chains | OCP | Strategy pattern or registry |
| Override that throws | LSP | Honor base contract or don't inherit |
| 10+ method interface | ISP | Split into focused interfaces |
| in logic | DIP | Dependency injection |
Let It Crash Gate
Detects anti-patterns in error handling based on the "Let It Crash" philosophy.
| Pattern | Severity | Description |
|---|
| Bare | error | Catches all exceptions including KeyboardInterrupt |
| (no re-raise) | warning | Swallows errors without handling |
| error | Silent failure, debugging nightmare |
| Defensive chains | warning | Masks root cause of bugs |
| Nested try/except fallbacks | warning | Complex error paths, hard to debug |
When to Let It Crash:
- Validation failures → crash with clear error
- Programming errors → surface immediately
- Internal operations → let them fail
When to Handle Errors (exceptions to rule):
- Data persistence → protect against data loss
- External APIs → retry, fallback, graceful degradation
- Resource cleanup → RAII, finally blocks
- User-facing operations → graceful error messages
Not Flagged (appropriate handling):
- Error handling in , , paths
- Explicit logging before swallowing
- Re-raise after logging
Flags
| Flag | Type | Default | Description |
|---|
| bool | false | Run only KISS validation |
| bool | false | Run only purity validation |
| bool | false | Run only SOLID validation |
| bool | false | Run only Let It Crash validation |
| bool | false | Skip KISS validation |
| bool | false | Skip purity validation |
| bool | false | Skip SOLID validation |
| bool | false | Skip Let It Crash validation |
| int | 10 | Max cyclomatic complexity |
| int | 15 | Max cognitive complexity |
| int | 50 | Max function line count |
| int | 4 | Max nesting depth |
| int | 5 | Max parameter count |
| int | 300 | Max file line count (SRP) |
| int | 7 | Max interface methods (ISP) |
| bool | false | Treat all warnings as errors |
| bool | false | Only validate core layer files |
| bool | false | Analyze all files, not just changed |
| bool | false | Generate detailed JSON report |
Integration Flags
For use by other skills and pre-commit hooks:
| Flag | Description |
|---|
| Run as pre-commit hook (blocks commit on failure) |
| Real-time validation during implementation |
| Output JSON format for programmatic use |
Exit Codes
| Code | Meaning | Action |
|---|
| 0 | Validation passed | Proceed |
| 2 | Violations detected | Blocked - refactor required |
| 3 | Validation error | Manual intervention needed |
Personas Activated
- code-warden - Primary reviewer for principles enforcement
- refactoring-expert - For complex refactoring guidance
- quality-engineer - For metrics integration
Validator Scripts
validate_kiss.py
bash
python .claude/skills/sc-principles/scripts/validate_kiss.py \
--scope-root . \
--threshold 10 \
--max-lines 50 \
--json
validate_purity.py
bash
python .claude/skills/sc-principles/scripts/validate_purity.py \
--scope-root . \
--core-only \
--json
Pre-commit Integration
yaml
repos:
- repo: local
hooks:
- id: kiss-check
name: KISS Validation
entry: python .claude/skills/sc-principles/scripts/validate_kiss.py --scope-root . --json
language: python
types: [python]
pass_filenames: false
- id: purity-check
name: Purity Validation
entry: python .claude/skills/sc-principles/scripts/validate_purity.py --scope-root . --json
language: python
types: [python]
pass_filenames: false
Refactoring Guidance
When violations are detected, apply these patterns:
For Complexity Violations
- Extract Method - Split large functions into smaller, named pieces
- Guard Clauses - Replace nested if/else with early returns
- Strategy Pattern - Replace complex switch/if-else with polymorphism
- Decompose Conditional - Name complex conditions as explaining variables
Before:
python
def process(data, config, user):
if data:
if config.enabled:
if user.has_permission:
for item in data:
if item.valid:
# deep logic here
After:
python
def process(data, config, user):
if not can_process(data, config, user):
return None
return process_items(data)
def can_process(data, config, user):
return data and config.enabled and user.has_permission
def process_items(data):
return [process_item(item) for item in data if item.valid]
For Purity Violations
- Dependency Injection - Pass dependencies as arguments
- Repository Pattern - Isolate database operations
- Adapter Pattern - Wrap external APIs
- Return Don't Print - Return values, let callers handle output
Before:
python
# In domain/calculator.py (CORE - should be pure)
def calculate_discount(user_id):
user = db.query(User).get(user_id) # I/O in core!
print(f"Calculating for {user.name}") # Side effect!
return 0.2 if user.is_premium else 0.1
After:
python
# In domain/calculator.py (CORE - now pure)
def calculate_discount(user: User) -> float:
"""Pure function - no I/O, just logic."""
return 0.2 if user.is_premium else 0.1
# In adapters/discount_service.py (SHELL - I/O allowed)
def get_user_discount(user_id: int) -> float:
user = user_repository.get(user_id)
discount = calculate_discount(user)
logger.info(f"Discount for {user.name}: {discount}")
return discount
For SOLID Violations
- SRP (Single Responsibility) - Extract into modules
- OCP (Open-Closed) - Use strategy pattern or registry
- LSP (Liskov Substitution) - Honor base contracts
- ISP (Interface Segregation) - Split fat interfaces
- DIP (Dependency Inversion) - Inject dependencies
Before (OCP violation):
python
def process_payment(payment_type, amount):
if payment_type == "credit":
return process_credit(amount)
elif payment_type == "debit":
return process_debit(amount)
elif payment_type == "crypto": # New type = code change!
return process_crypto(amount)
After (OCP compliant):
python
PROCESSORS = {
"credit": process_credit,
"debit": process_debit,
"crypto": process_crypto, # Add here, no function change
}
def process_payment(payment_type, amount):
processor = PROCESSORS.get(payment_type)
if not processor:
raise ValueError(f"Unknown payment type: {payment_type}")
return processor(amount)
For Let It Crash Violations
- Remove catch-all blocks - Let bugs surface
- Remove defensive guards - Validate at boundaries instead
- Flatten try/except - Handle at edges, not everywhere
Before (catch-all anti-pattern):
python
def get_user(user_id):
try:
user = db.query(User).get(user_id)
return user
except: # BAD: catches everything, hides bugs
return None
After (let it crash):
python
def get_user(user_id):
# Let database errors surface - they indicate real problems
return db.query(User).get(user_id)
# Handle at the boundary (API layer)
@app.get("/users/{user_id}")
def api_get_user(user_id: int):
try:
return get_user(user_id)
except DBError as e:
logger.error("Database error", error=e, user_id=user_id)
raise HTTPException(500, "Database unavailable")
Examples
Example 1: Full Validation
bash
$ /sc:principles src/ --report
KISS Validation: BLOCKED
Files analyzed: 12
Errors: 3, Warnings: 5
Violations:
[ERROR] src/services/order.py:45 process_order: complexity = 15 (max: 10)
[ERROR] src/utils/parser.py:12 parse_data: length = 78 (max: 50)
[WARNING] src/domain/calc.py:8 calculate: parameters = 7 (max: 5)
Purity Validation: BLOCKED
Core violations: 2, Shell warnings: 1
Violations:
[ERROR] src/domain/user.py:23 get_status: database - db.query (context: core)
[ERROR] src/services/report.py:56 generate: file_io - open (context: core)
Recommendations:
- COMPLEXITY: Extract helper functions, use early returns
- DATABASE: Use repository pattern. Business logic receives data, not queries
- FILE I/O: Move file operations to adapter layer
Example 2: KISS Only
bash
$ /sc:principles src/ --kiss-only --threshold 8
KISS Validation: PASSED
Files analyzed: 12
Errors: 0, Warnings: 2
Example 3: Strict Mode
bash
$ /sc:principles src/ --strict
# All warnings become errors
# Any warning will block
Quality Integration
This skill integrates with SuperClaude quality gates:
- Contributes to dimension (weight: 0.08)
- Contributes to dimension (weight: 0.02)
- Triggers strategy when simplicity < 70
- Triggers strategy when purity < 70
Related Skills
/sc:improve --type principles
- Auto-refactor for principles compliance
- - Includes principles validation by default
- - Code analysis includes principles metrics
Test Coverage
The validators have comprehensive test coverage (27 tests):
Purity Validator Tests:
- Async function detection ()
- Await expression detection
- Async for loop detection
- Async with context manager detection
- Shell vs core severity differentiation
- Edge cases (syntax errors, unicode, empty files)
KISS Validator Tests:
- Function length (inclusive count)
- Cyclomatic complexity
- Cognitive complexity
- Nesting depth
- Parameter count
- Edge cases (syntax errors, unicode, empty files)
Run tests:
bash
python -m pytest .claude/skills/sc-principles/tests/ -v
Version: 2.0.0
Validators:
,
,
(heuristic),
(heuristic)
Agent:
Traits:
,
Tests: 27 passing (KISS + Purity)