diff --git a/.claude/skills/apply-solid.md b/.claude/skills/apply-solid.md new file mode 100644 index 0000000..ea2e017 --- /dev/null +++ b/.claude/skills/apply-solid.md @@ -0,0 +1,82 @@ +--- +name: apply-solid +description: Use when designing classes or refactoring - applies SOLID principles pragmatically, only when there's a clear benefit +--- + +# SOLID Principles (Pragmatic Application) + +## Core Rule + +**Apply SOLID only when there's a clear, immediate benefit. Don't over-engineer.** + +## When to Apply + +| Principle | Apply When | Skip When | +|-----------|------------|-----------| +| **S**ingle Responsibility | Class doing 3+ unrelated things | Simple class, cohesive methods | +| **O**pen/Closed | Behavior extended frequently | One-off, unlikely to change | +| **L**iskov Substitution | Building class hierarchies | No inheritance | +| **I**nterface Segregation | Large interfaces force unused deps | Already small and focused | +| **D**ependency Inversion | Need to swap implementations | Dependency is stable | + +## Decision Framework + +Before applying, ask: + +1. Is there a **real problem NOW**? +2. Will this make code **easier to understand**? +3. Is abstraction worth the **added complexity**? +4. Would a **simpler solution** work? + +**If unsure, keep it simple. Refactor when real need arises.** + +## Examples + +### Single Responsibility - APPLY + +```ruby +# BAD: Controller doing everything +class JobsController + def index + # querying + filtering + sorting + + # pagination + formatting + caching + end +end + +# GOOD: Extract query logic +class JobsController + def index + @jobs = JobQuery.new(params).execute + end +end +``` + +### Single Responsibility - DON'T APPLY + +```ruby +# This is FINE - don't over-split +class Job + def formatted_created_at + created_at.strftime("%Y-%m-%d") + end + + def status_label + status.humanize + end +end +``` + +## Red Flags (Over-engineering) + +- Creating abstraction for single use case +- Building for "future requirements" +- Interface with one implementation +- Factory that creates one type +- 3 similar lines → premature abstraction + +## The Test + +> "If I needed to change this, would SOLID make it easier or harder?" + +Easier → Apply it +Harder or same → Keep it simple diff --git a/.claude/skills/commit-style.md b/.claude/skills/commit-style.md new file mode 100644 index 0000000..53fdc47 --- /dev/null +++ b/.claude/skills/commit-style.md @@ -0,0 +1,59 @@ +--- +name: commit-style +description: Use when creating git commits - ensures consistent commit message format and atomic commits +--- + +# Commit Style Guide + +## Format + +``` +: + +[optional body] +``` + +## Types + +| Type | Use For | +|------|---------| +| `feat` | New feature | +| `fix` | Bug fix | +| `refactor` | Code restructuring (no behavior change) | +| `docs` | Documentation only | +| `test` | Adding or fixing tests | +| `chore` | Maintenance (deps, configs) | +| `perf` | Performance improvement | +| `style` | Formatting, whitespace | + +## Rules + +1. **Subject**: Max 50 chars, imperative mood ("add" not "added") +2. **Body**: Explain "what" and "why", not "how" +3. **Atomic**: One logical change per commit + +## Examples + +``` +feat: add full-text search for jobs + +Implements search across job class names and arguments. +Uses SQL LIKE with proper escaping. +``` + +``` +fix: prevent N+1 query in jobs index + +Eager load queue records to reduce queries from O(n) to O(1). +``` + +``` +refactor: extract job filtering to query object +``` + +## Anti-patterns + +- `fix: stuff` (vague) +- `updated files` (meaningless) +- `WIP` on branches to be merged +- Multiple unrelated changes in one commit diff --git a/.claude/skills/create-pr.md b/.claude/skills/create-pr.md new file mode 100644 index 0000000..e7f824a --- /dev/null +++ b/.claude/skills/create-pr.md @@ -0,0 +1,64 @@ +--- +name: create-pr +description: Use when creating a pull request - follows PR template with summary, problem, solution, and testing checklist +--- + +# Create Pull Request + +## PR Template + +```markdown +## Summary + + +## Problem + + +## Solution + + +## Changes + +- +- + +## Testing + +- [ ] Unit tests added/updated +- [ ] Manual testing completed +- [ ] Edge cases considered + +## Screenshots (if UI changes) + + +## Checklist +- [ ] Code follows project patterns +- [ ] Self-review completed +- [ ] Tests pass +- [ ] No debug statements left +``` + +## Before Creating PR + +1. Ensure all commits follow commit-style +2. Rebase on latest main if needed +3. Run full test suite locally +4. Self-review all changes (`git diff main...HEAD`) + +## PR Title + +- Keep under 70 chars +- Use same format as commits: `type: description` +- Examples: + - `feat: add job search functionality` + - `fix: resolve N+1 query in workers index` + +## Command + +```bash +gh pr create --title "type: description" --body "$(cat <<'EOF' +## Summary +... +EOF +)" +``` diff --git a/.claude/skills/principal-thinking.md b/.claude/skills/principal-thinking.md new file mode 100644 index 0000000..c38d873 --- /dev/null +++ b/.claude/skills/principal-thinking.md @@ -0,0 +1,54 @@ +--- +name: principal-thinking +description: Use when starting any feature, refactor, or significant code change - applies principal engineer level analysis before implementation +--- + +# Principal Engineer Thinking + +## Overview + +Think like a principal engineer: understand deeply before acting, consider trade-offs, anticipate problems. + +## Before Writing Code + +1. **Understand the "why"** + - What problem are we solving? + - Why does it matter to users? + - What happens if we don't solve it? + +2. **Explore existing solutions** + - How is this handled elsewhere in the codebase? + - Are there gems/libraries that solve this? + - What patterns are already established? + +3. **Consider trade-offs** + - What are the options? + - Pros/cons of each? + - Document the decision and reasoning + +4. **Think about scale** + - Will this work with 10x data? + - What are the performance implications? + - Are there N+1 queries or memory concerns? + +5. **Identify risks and edge cases** + - What could go wrong? + - What are the boundary conditions? + - How do we handle failures gracefully? + +## During Implementation + +| Principle | Question to Ask | +|-----------|-----------------| +| Simplicity | Is there a simpler way? | +| Readability | Will someone understand this in 6 months? | +| Failure handling | What happens when this fails? | +| Backwards compatibility | Does this break existing functionality? | +| Observability | Can we debug this in production? | + +## After Implementation + +- [ ] Would I approve this in a code review? +- [ ] Is the "why" documented for non-obvious decisions? +- [ ] Is this easy to modify later? +- [ ] Did I add unnecessary complexity? diff --git a/.claude/skills/review-code.md b/.claude/skills/review-code.md new file mode 100644 index 0000000..ff06871 --- /dev/null +++ b/.claude/skills/review-code.md @@ -0,0 +1,64 @@ +--- +name: review-code +description: Use when completing a feature or before creating PR - comprehensive code review checklist for self-review or peer review +--- + +# Code Review Checklist + +## 1. Correctness + +- [ ] Does the code do what it's supposed to do? +- [ ] Are edge cases handled? +- [ ] Are there off-by-one errors? +- [ ] Is error handling appropriate? + +## 2. Security + +- [ ] SQL injection vulnerabilities? +- [ ] XSS vulnerabilities? +- [ ] Sensitive data exposure in logs/errors? +- [ ] Authorization checks in place? + +## 3. Performance + +- [ ] N+1 queries? +- [ ] Unnecessary database calls? +- [ ] Expensive operations in loops? +- [ ] Missing indexes for queries? + +## 4. Maintainability + +- [ ] Is the code readable without comments? +- [ ] Are names descriptive and consistent? +- [ ] Is there unnecessary complexity? +- [ ] Will this be easy to modify? + +## 5. Consistency + +- [ ] Follows existing codebase patterns? +- [ ] Matches naming conventions? +- [ ] Similar to how other features are built? + +## 6. Testing + +- [ ] Tests cover happy path? +- [ ] Tests cover edge cases? +- [ ] Tests cover error scenarios? +- [ ] Tests are readable and maintainable? + +## Common Issues to Watch + +| Issue | Look For | +|-------|----------| +| N+1 queries | Loops that trigger DB calls | +| Missing validation | User input going directly to DB | +| Error swallowing | Empty rescue blocks | +| Hardcoded values | Magic numbers/strings | +| Dead code | Unused methods/variables | + +## After Review + +If issues found: +1. Fix the issues +2. Re-run this checklist +3. Only proceed when all checks pass diff --git a/.claude/skills/write-tests.md b/.claude/skills/write-tests.md new file mode 100644 index 0000000..956d080 --- /dev/null +++ b/.claude/skills/write-tests.md @@ -0,0 +1,74 @@ +--- +name: write-tests +description: Use when writing test cases - ensures robust, comprehensive tests following best practices and proper structure +--- + +# Writing Robust Tests + +## Principles + +1. **Test behavior, not implementation** - Verify what code does, not how +2. **One concept per test** - Each test verifies one thing +3. **Readable names** - Describe scenario and expectation +4. **Arrange-Act-Assert** - Clear structure + +## Test Structure (RSpec) + +```ruby +describe "ClassName" do + describe "#method_name" do + context "when [condition]" do + it "does [expected behavior]" do + # Arrange - setup + # Act - call method + # Assert - verify + end + end + end +end +``` + +## What to Test + +| Category | Examples | +|----------|----------| +| Happy path | Normal expected usage | +| Edge cases | Empty, nil, boundaries | +| Error cases | Invalid input, failures | +| Security | Auth, input validation | + +## Naming Convention + +```ruby +# Format: "verb_outcome_when_condition" +it "returns empty array when no jobs exist" +it "raises error when job_id is nil" +it "filters by status when status param provided" +``` + +## Test Quality Checklist + +- [ ] Tests are independent (no shared mutable state) +- [ ] Tests are deterministic (same result every run) +- [ ] Tests are fast (mock external services) +- [ ] Tests are readable (clear setup, obvious assertions) +- [ ] Critical paths covered +- [ ] Edge cases covered +- [ ] Error handling verified + +## Anti-patterns + +| Don't | Do Instead | +|-------|------------| +| Test private methods | Test public interface | +| Depend on test order | Independent tests | +| Use sleep for timing | Use proper waiting | +| Hardcode IDs | Use factories | +| Test framework code | Test your code | + +## Coverage Goals + +- All public methods +- All conditional branches +- All error paths +- Boundary conditions diff --git a/.gitignore b/.gitignore index 0d3fea3..3e30ded 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ .rspec_status *.gem + +# Git worktrees for parallel development +.worktrees/ diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..9c25013 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.3.6 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ee85897 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,45 @@ +# Project Instructions + +## Git Workflow + +### Protected Branches +The following branches are protected and must **never** receive direct commits or pushes: +- `main` +- `master` +- `dev` +- `staging` + +### Branch Creation Rules +- **Always create a new branch** before starting work on any feature, task, or bug fix +- **Always branch from `main` or `master`** (whichever exists in the repo) +- Before creating a branch, ensure you're on the base branch and it's up to date +- Use descriptive branch names (e.g., `feature/add-search`, `fix/login-bug`) + +### Worktree Directory +- Use `.worktrees/` for git worktrees (already in .gitignore) + +## Planning Mode + +- **Always use plan mode** for complex tasks before writing any code +- Complex tasks: new features, significant refactors, multi-file changes, architectural decisions + +## Project Skills + +Custom workflows available in `.claude/skills/`: + +| Skill | When to Use | +|-------|-------------| +| `principal-thinking` | Starting any feature or significant change | +| `commit-style` | Creating git commits | +| `create-pr` | Creating pull requests | +| `review-code` | Before completing a feature or creating PR | +| `write-tests` | Writing test cases | +| `apply-solid` | Designing classes or refactoring | + +**Invoke with:** `/skill-name` or reference during work + +## Tech Stack + +- **Ruby/Rails:** Follow Rails conventions, use ActiveRecord properly +- **JavaScript:** Modern ES6+ patterns +- **CSS:** Follow existing naming conventions