skills/tony363/superclaude/sc-principles

sc-principles

SKILL.md

/sc:principles - Code Principles Validator

Mandatory validation skill enforcing four fundamental software engineering principles:

  1. KISS (Keep It Simple, Stupid) - Code should be as simple as possible
  2. Functional Core, Imperative Shell - Business logic must be pure; I/O belongs at edges
  3. SOLID - Single Responsibility, Open-Closed, Liskov Substitution, Interface Segregation, Dependency Inversion
  4. Let It Crash - Fail fast for bugs; handle errors explicitly at boundaries

Quick Start

# 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: 1 + nesting_depth per control structure
  • Example: if (if (if ...)) 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 */domain/*, */logic/*, */services/*, */utils/*, */core/* NO error
Shell */handlers/*, */adapters/*, */api/*, */cli/*, */scripts/*, */tests/* YES warning

Note: Files in */archive/*, */examples/*, */benchmarks/*, conftest.py, setup.py, and *__main__.py are treated as shell (I/O allowed).

Detected I/O Patterns:

Category Examples
File I/O open(), read(), write(), Path.read_text()
Network requests.get(), httpx, urllib, socket
Database execute(), query(), session.add(), cursor
Subprocess subprocess.run(), os.system(), Popen
Global State global, nonlocal keywords
Side Effects print(), logging.*, logger.*
Async I/O async def, await, async for, async with

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 if/elif chains on type, isinstance cascades warning Open-Closed - extend, don't modify
LSP Override that raises NotImplementedError 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
new Service() 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 except: error Catches all exceptions including KeyboardInterrupt
except Exception: (no re-raise) warning Swallows errors without handling
except: pass error Silent failure, debugging nightmare
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 */adapters/*, */api/*, */cli/* paths
  • Explicit logging before swallowing
  • Re-raise after logging

Flags

Flag Type Default Description
--kiss-only bool false Run only KISS validation
--purity-only bool false Run only purity validation
--solid-only bool false Run only SOLID validation
--crash-only bool false Run only Let It Crash validation
--no-kiss bool false Skip KISS validation
--no-purity bool false Skip purity validation
--no-solid bool false Skip SOLID validation
--no-crash bool false Skip Let It Crash validation
--threshold int 10 Max cyclomatic complexity
--max-cognitive int 15 Max cognitive complexity
--max-lines int 50 Max function line count
--max-depth int 4 Max nesting depth
--max-params int 5 Max parameter count
--max-file-lines int 300 Max file line count (SRP)
--max-interface-methods int 7 Max interface methods (ISP)
--strict bool false Treat all warnings as errors
--core-only bool false Only validate core layer files
--all bool false Analyze all files, not just changed
--report bool false Generate detailed JSON report

Integration Flags

For use by other skills and pre-commit hooks:

Flag Description
--pre-commit Run as pre-commit hook (blocks commit on failure)
--inline Real-time validation during implementation
--json 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
  • optimizer - For complex refactoring guidance
  • guardian - For metrics integration

Validator Scripts

Located in scripts/ directory:

validate_kiss.py

python .claude/skills/sc-principles/scripts/validate_kiss.py \
  --scope-root . \
  --threshold 10 \
  --max-lines 50 \
  --json

validate_purity.py

python .claude/skills/sc-principles/scripts/validate_purity.py \
  --scope-root . \
  --core-only \
  --json

Pre-commit Integration

Add to .pre-commit-config.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

  1. Extract Method - Split large functions into smaller, named pieces
  2. Guard Clauses - Replace nested if/else with early returns
  3. Strategy Pattern - Replace complex switch/if-else with polymorphism
  4. Decompose Conditional - Name complex conditions as explaining variables

Before:

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:

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

  1. Dependency Injection - Pass dependencies as arguments
  2. Repository Pattern - Isolate database operations
  3. Adapter Pattern - Wrap external APIs
  4. Return Don't Print - Return values, let callers handle output

Before:

# 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:

# 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

  1. SRP (Single Responsibility) - Extract into modules
  2. OCP (Open-Closed) - Use strategy pattern or registry
  3. LSP (Liskov Substitution) - Honor base contracts
  4. ISP (Interface Segregation) - Split fat interfaces
  5. DIP (Dependency Inversion) - Inject dependencies

Before (OCP violation):

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):

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

  1. Remove catch-all blocks - Let bugs surface
  2. Remove defensive guards - Validate at boundaries instead
  3. Flatten try/except - Handle at edges, not everywhere

Before (catch-all anti-pattern):

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):

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

$ /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

$ /sc:principles src/ --kiss-only --threshold 8

KISS Validation: PASSED
Files analyzed: 12
Errors: 0, Warnings: 2

Example 3: Strict Mode

$ /sc:principles src/ --strict

# All warnings become errors
# Any warning will block

Quality Integration

This skill integrates with SuperClaude quality gates:

  • Contributes to simplicity dimension (weight: 0.08)
  • Contributes to purity dimension (weight: 0.02)
  • Triggers simplification strategy when simplicity < 70
  • Triggers purification strategy when purity < 70

Related Skills

  • /sc:improve --type principles - Auto-refactor for principles compliance
  • /sc:implement - Includes principles validation by default
  • /sc:analyze - Code analysis includes principles metrics

Test Coverage

The validators have comprehensive test coverage (59 tests across 4 suites):

Purity Validator Tests (16):

  • Async function detection (async def)
  • Await expression detection
  • Async for loop detection
  • Async with context manager detection
  • Shell vs core severity differentiation
  • False positive regression (set.add, parser.add_argument, asyncio.run, callback.call)
  • Edge cases (syntax errors, unicode, empty files)

KISS Validator Tests (15):

  • Function length (inclusive count)
  • Cyclomatic complexity
  • Cognitive complexity
  • Nesting depth
  • Parameter count
  • Edge cases (syntax errors, unicode, empty files)

SOLID Validator Tests (15):

  • SRP: File length, class method count, private methods excluded
  • OCP: isinstance cascades
  • LSP: NotImplementedError in concrete overrides, ABC/Protocol excluded
  • ISP: Fat Protocol and ABC interfaces
  • DIP: Direct service instantiation in core paths
  • Edge cases (syntax errors, empty files)

Crash Validator Tests (13):

  • Bare except detection
  • except: pass detection
  • Exception swallowed in core paths
  • Exception with re-raise (OK)
  • Specific exception handling (OK)
  • Nested try/except depth
  • Shell path relaxation (adapters, api)
  • Edge cases (syntax errors, empty files, try/finally)

Run tests:

python -m pytest .claude/skills/sc-principles/tests/ -v

Version: 2.1.0 Validators: validate_kiss.py, validate_purity.py, validate_solid.py, validate_crash.py Shared: shared.py (common find_python_files utility) Agent: code-warden Traits: principles-enforced Tests: 59 passing (all 4 validators)

Weekly Installs
24
GitHub Stars
16
First Seen
Jan 23, 2026
Installed on
codex21
opencode21
gemini-cli20
cursor20
claude-code19
antigravity18