Agent Skills: Software Engineering

Apply software engineering best practices, design principles, and avoid common anti-patterns. Use when designing systems, reviewing code quality, refactoring legacy code, making architectural decisions, or improving maintainability.

UncategorizedID: knoopx/pi/swe

Install this agent skill to your local

pnpm dlx add-skill https://github.com/knoopx/pi/tree/HEAD/agent/skills/swe

Skill Files

Browse the full folder contents for swe.

Download Skill

Loading file tree…

agent/skills/swe/SKILL.md

Skill Metadata

Name
swe
Description
Applies software engineering best practices, design principles, and avoids common anti-patterns. Use when designing systems, reviewing code quality, refactoring legacy code, making architectural decisions, or improving maintainability.

Software Engineering

Core Principles

| Principle | Meaning | | --------------------- | ------------------------------------------------------- | | Simplicity | Simplest code that works; complexity only when required | | Single Responsibility | Each function/class/module does one thing | | Self-Documenting | Code explains itself; comments are a smell | | Fail Fast | Validate early, propagate unexpected errors | | Test Behavior | What code does, not implementation | | No Backwards Compat | Don't add legacy support unless requested | | Consistency | Match project conventions over preference |


Design

SOLID

| Principle | Violation Sign | | ------------------------- | ---------------------------------------- | | Single Responsibility | Class doing too many things | | Open/Closed | Modifying existing code for new features | | Liskov Substitution | Overridden methods breaking contracts | | Interface Segregation | Clients depend on unused methods | | Dependency Inversion | High-level imports low-level details |

Architecture

Presentation → Application → Domain ← Infrastructure
                    ↓
           Dependencies point DOWN only

Rules:

  • Domain depends on nothing
  • Infrastructure implements domain interfaces
  • No circular dependencies

Design Patterns

Use when solving real problems, not preemptively:

| Pattern | Use When | | -------- | --------------------------------- | | Factory | Complex object creation | | Builder | Many optional parameters | | Adapter | Incompatible interfaces | | Facade | Simplifying subsystem | | Strategy | Runtime algorithm selection | | Observer | Many dependents need notification |

Security

  • Validate all external input (allowlists > denylists)
  • Encrypt sensitive data at rest and transit
  • Never log secrets
  • Parameterized queries (SQL injection)
  • Escape output (XSS)

Implementation

Naming

| Type | Convention | Example | | --------- | ----------------------- | --------------------------- | | Variables | camelCase noun | userName, isValid | | Functions | camelCase verb | getUser, validateInput | | Booleans | is/has/can prefix | isActive, hasPermission | | Constants | UPPER_SNAKE | MAX_RETRIES | | Classes | PascalCase noun | UserService |

Rules:

  • Names reveal intent
  • No single-letter params
  • No abbreviations (uruserRepository)

Self-Documenting Code

// ❌ Comment hiding bad code
if (u.r === 1 && u.s !== 0) { ... }

// ✅ Self-documenting
if (user.isAdmin && user.isActive) { ... }

Acceptable comments: RFC links, bug tracker refs, non-obvious warnings

Functions

| Do | Don't | | ------------------------ | -------------------------- | | Small, focused | God functions (100+ lines) | | 2-3 params max | 6+ parameters | | Return early | Deep nesting | | Pure when possible | Hidden side effects | | Single abstraction level | Mixed levels |

Error Handling

// ❌ Silent catch
try {
  await save(user);
} catch (e) {}

// ❌ Log only
try {
  await save(user);
} catch (e) {
  console.log(e);
}

// ✅ Let propagate or handle specific
try {
  await save(user);
} catch (e) {
  if (e instanceof DuplicateEmail) return { error: "Email taken" };
  throw e;
}

Rules:

  • Empty catch = always wrong
  • Catch only what you can handle
  • Re-throw with context or propagate
  • Crash visibly > fail silently

File Organization

  • Match existing conventions
  • No barrel files (index.ts re-exports)
  • Import from concrete modules
  • Co-locate tests with source
src/users/
  user-service.ts
  user-service.test.ts

Code Smells

| Smell | Fix | | ------------------- | ------------------------- | | God Class | Split by responsibility | | Feature Envy | Move method to data owner | | Long Param List | Parameter object | | Primitive Obsession | Value objects | | Dead Code | Delete it |

Linting

| Tool | Purpose | | ------------ | ------------------------ | | Formatter | Style (Prettier, dprint) | | Linter | Quality (ESLint, Ruff) | | Type Checker | Safety (tsc, mypy) |

Rules:

  • Automate formatting
  • Zero warnings in CI
  • Never disable rules—fix the code

Testing

Test Pyramid

    E2E (few) - Critical journeys, slow
   Integration (some) - Component interactions
  Unit (many) - Fast, isolated, business logic

What to Test

| Test | Skip | | -------------- | ----------------- | | Business logic | Framework code | | Edge cases | Trivial getters | | Error paths | Third-party libs | | Public API | Private internals |

Test Quality

  • Independent and isolated
  • Deterministic (no flakiness)
  • Fast (< 100ms unit)
  • Single reason to fail
  • Test behavior, not implementation

BDD Structure

describe("UserService", () => {
  describe("given valid data", () => {
    describe("when creating user", () => {
      it("then persists with ID", async () => {
        // arrange, act, assert
      });
    });
  });
});

Anti-Patterns

| Pattern | Fix | | ---------------------- | --------------------- | | Ice Cream Cone | More unit, fewer E2E | | Flaky Tests | Fix races, use mocks | | Testing Implementation | Test behavior | | No Assertions | Add meaningful checks |


Review

Before PR

  • [ ] Type check passes
  • [ ] Lint passes
  • [ ] Tests pass
  • [ ] No debug/console.log
  • [ ] No commented code
  • [ ] Up to date with main

Review Checklist

Correctness:

  • Does it work? Edge cases? Error handling?

Design:

  • Right abstraction? SOLID? Dependencies appropriate?

Readability:

  • Clear names? Straightforward logic? No unnecessary comments?

Security:

  • Input validated? No injection? Secrets handled?

Performance:

  • No N+1? No await in loops? Caching considered?

Tests:

  • Sufficient coverage? Edge cases? Behavior-focused?

For Reviewers

  • Code, not author
  • Questions > demands
  • Explain the "why"
  • Blocking vs nitpick

For Authors

  • Small, focused PRs
  • Context in description
  • Respond to all comments

Maintenance

Refactoring

  1. Ensure test coverage first
  2. Small, incremental changes
  3. Run tests after each change
  4. Refactor OR add features, never both

| Technique | When | | ---------------------- | ---------------------------- | | Extract Method | Long method, reusable logic | | Extract Class | Multiple responsibilities | | Move Method | Uses other class's data more | | Introduce Param Object | Long parameter lists |

Technical Debt

| Type | Handling | | ------------- | -------------------------- | | Deliberate | Document, schedule payback | | Accidental | Fix when discovered | | Bit Rot | Regular maintenance | | Outdated Deps | Regular updates |

Find: unused code, duplicates, circular deps, outdated deps

Performance

  1. Don't optimize prematurely
  2. Measure before optimizing
  3. Focus on hot paths

| Pitfall | Fix | | ------------ | ------------------ | | N+1 queries | Batch, joins | | Blocking I/O | Async | | Memory leaks | Weak refs, cleanup |

Documentation

| Document | Skip | | -------------------- | ---------------------- | | Public APIs | Obvious code | | ADRs | Implementation details | | Setup/deploy | Self-documenting code | | Non-obvious behavior | Every function |


Anti-Patterns

| Pattern | Problem | Fix | | ---------------- | ----------------- | ----------------- | | Big Ball of Mud | No structure | Define boundaries | | Spaghetti Code | Tangled | Modularize | | Lava Flow | Dead code | Delete it | | Copy-Paste | Duplication | Extract | | Magic Numbers | No context | Named constants | | Circular Deps | Coupling | Abstraction layer | | Feature Flags | Hidden complexity | One code path | | Backwards Compat | Legacy burden | Replace entirely |