Pre-Commit Quality Review
Review the staged changes in this commit for code quality issues before committing.
Objectives
- Fast: Complete review in < 30 seconds
- Focused: Only review staged Ruby files
- Actionable: Clear pass/fail with specific fixes
- Non-interactive: Works in headless mode
- Expert-driven: Apply Ruby best practices from industry experts
Expert Panel
Apply principles from these Ruby/software design experts:
- Sandi Metz - POODR principles, small methods/classes, SRP, DRY
- Jeremy Evans - Sequel best practices, transaction safety, performance
- Kent Beck - Simple design, revealing names, Command-Query Separation
- Avdi Grimm - Confident Ruby, null objects, tell-don't-ask, meaningful returns
- Gary Bernhardt - Functional core/imperative shell, fast tests, immutability
Review Process
Get staged files:
git diff --cached --name-only --diff-filter=ACM | grep '\.rb$'
For each staged Ruby file, check:
- Get the full diff:
git diff --cached <file>
- Review only the added/modified lines (lines starting with
+)
Look for critical issues (❌ BLOCK):
Sandi Metz violations:
- ❌ Missing
frozen_string_literal: true in new files
- ❌ Methods > 15 lines (SRP violation, too complex)
- ❌ Classes > 200 lines (god object)
- ❌ Obvious code duplication (DRY violation)
Jeremy Evans (Sequel) violations:
- ❌ Raw SQL strings instead of Sequel dataset methods
- ❌ Database writes without transaction wrapper
- ❌ N+1 queries (multiple queries in loops)
Kent Beck violations:
- ❌ Overly complex solutions (nested conditionals > 3 levels)
- ❌ Command-Query Separation violation (methods that both mutate and return calculated values)
Avdi Grimm violations:
- ❌ Defensive nil checks everywhere (should use null objects)
- ❌ Implicit nil returns in public methods
- ❌ Bare
raise or rescue without exception class
Gary Bernhardt violations:
- ❌ I/O operations mixed with business logic (should separate)
- ❌ Mutable state in value objects
- ❌ Database/file I/O in unit tests (makes tests slow)
Testing:
- ❌ New public methods without corresponding tests
Look for medium issues (⚠️ WARNING):
Sandi Metz:
- ⚠️ Methods 10-15 lines (consider extracting)
- ⚠️ Classes 100-200 lines (approaching god object)
- ⚠️ Method parameters > 3 (use parameter object)
Jeremy Evans:
- ⚠️ Missing indexes on foreign keys
- ⚠️ Connection not properly managed
Kent Beck:
- ⚠️ Poor naming (unclear variable/method names, abbreviations)
- ⚠️ Methods doing multiple things (and/or in method name)
Avdi Grimm:
- ⚠️ Law of Demeter violations (chained method calls like
foo.bar.baz.qux)
- ⚠️ Asking instead of telling (lots of getters instead of sending commands)
Gary Bernhardt:
- ⚠️ Business logic scattered in imperative shell
- ⚠️ Missing value objects (primitives passed around)
General:
- ⚠️ Missing documentation for public APIs
- ⚠️ Tight coupling between modules
Output Format
Provide a clear summary with expert attributions:
# Pre-Commit Quality Review
## Files Reviewed
- file1.rb (23 lines changed)
- file2.rb (8 lines changed)
## Status: ❌ BLOCK / ✅ PASS / ⚠️ WARNING
### Critical Issues ❌ (must fix before commit)
**Sandi Metz violations:**
- file1.rb:1 - Missing frozen_string_literal: true
- file2.rb:15-38 - Method too long (24 lines, max 15)
**Jeremy Evans violations:**
- file1.rb:42 - Raw SQL string instead of Sequel dataset method
- file1.rb:50 - Database write without transaction wrapper
**Avdi Grimm violations:**
- file2.rb:10 - Implicit nil return in public method
### Medium Issues ⚠️ (consider fixing)
**Sandi Metz:**
- file3.rb:20-32 - Method is 13 lines (consider extracting)
**Kent Beck:**
- file2.rb:5 - Variable name `x` is unclear (revealing intent)
**Avdi Grimm:**
- file3.rb:45 - Law of Demeter violation: user.account.settings.theme
### Recommendations
1. Add `frozen_string_literal: true` to file1.rb (Sandi Metz)
2. Convert raw SQL at file1.rb:42 to Sequel dataset (Jeremy Evans)
3. Wrap database write at file1.rb:50 in transaction (Jeremy Evans)
4. Extract file2.rb:15-38 into smaller methods (Sandi Metz)
5. Return explicit value instead of nil at file2.rb:10 (Avdi Grimm)
6. Rename `x` to describe what it contains (Kent Beck)
7. Extract file3.rb:20-32 for better readability (Sandi Metz)
8. Use tell-don't-ask at file3.rb:45 (Avdi Grimm)
## Suggested Actions
[If BLOCK] Run: git reset HEAD <files> && fix issues && git add <files>
[If WARNING] Consider fixing before commit or create a follow-up task
[If PASS] Commit looks good! 🚀
Exit Behavior
- Return clear judgment: BLOCK, WARNING, or PASS
- Be specific: Include file:line references for all issues
- Be helpful: Suggest concrete fixes
- Be fast: Don't over-analyze, focus on obvious problems
Quick Reference Checklist
For each added/modified line in the diff, scan for:
Sandi Metz:
Jeremy Evans:
Kent Beck:
Avdi Grimm:
Gary Bernhardt:
Success Criteria
The review is complete when:
- All staged Ruby files have been checked
- Clear BLOCK/WARNING/PASS verdict is given
- All critical issues have file:line references with expert attribution
- Concrete fix suggestions are provided with expert rationale
1---2name: review-commit3description: Quick quality review of staged changes for pre-commit validation. Checks Ruby best practices and flags critical issues.4---5
6# Pre-Commit Quality Review
7
8Review the staged changes in this commit for code quality issues before committing.
9
10## Objectives
11
12- **Fast**: Complete review in < 30 seconds
13- **Focused**: Only review staged Ruby files
14- **Actionable**: Clear pass/fail with specific fixes
15- **Non-interactive**: Works in headless mode
16- **Expert-driven**: Apply Ruby best practices from industry experts
17
18## Expert Panel
19
20Apply principles from these Ruby/software design experts:
21
221. **Sandi Metz** - POODR principles, small methods/classes, SRP, DRY
232. **Jeremy Evans** - Sequel best practices, transaction safety, performance
243. **Kent Beck** - Simple design, revealing names, Command-Query Separation
254. **Avdi Grimm** - Confident Ruby, null objects, tell-don't-ask, meaningful returns
265. **Gary Bernhardt** - Functional core/imperative shell, fast tests, immutability
27
28## Review Process
29
301. **Get staged files:**
31 ```bash
32 git diff --cached --name-only --diff-filter=ACM | grep '\.rb$'
33 ```
34
352. **For each staged Ruby file, check:**
36 - Get the full diff: `git diff --cached <file>`
37 - Review only the added/modified lines (lines starting with `+`)
38
393. **Look for critical issues (❌ BLOCK):**
40
41 **Sandi Metz violations:**
42 - ❌ Missing `frozen_string_literal: true` in new files
43 - ❌ Methods > 15 lines (SRP violation, too complex)
44 - ❌ Classes > 200 lines (god object)
45 - ❌ Obvious code duplication (DRY violation)
46
47 **Jeremy Evans (Sequel) violations:**
48 - ❌ Raw SQL strings instead of Sequel dataset methods
49 - ❌ Database writes without transaction wrapper
50 - ❌ N+1 queries (multiple queries in loops)
51
52 **Kent Beck violations:**
53 - ❌ Overly complex solutions (nested conditionals > 3 levels)
54 - ❌ Command-Query Separation violation (methods that both mutate and return calculated values)
55
56 **Avdi Grimm violations:**
57 - ❌ Defensive nil checks everywhere (should use null objects)
58 - ❌ Implicit nil returns in public methods
59 - ❌ Bare `raise` or `rescue` without exception class
60
61 **Gary Bernhardt violations:**
62 - ❌ I/O operations mixed with business logic (should separate)
63 - ❌ Mutable state in value objects
64 - ❌ Database/file I/O in unit tests (makes tests slow)
65
66 **Testing:**
67 - ❌ New public methods without corresponding tests
68
694. **Look for medium issues (⚠️ WARNING):**
70
71 **Sandi Metz:**
72 - ⚠️ Methods 10-15 lines (consider extracting)
73 - ⚠️ Classes 100-200 lines (approaching god object)
74 - ⚠️ Method parameters > 3 (use parameter object)
75
76 **Jeremy Evans:**
77 - ⚠️ Missing indexes on foreign keys
78 - ⚠️ Connection not properly managed
79
80 **Kent Beck:**
81 - ⚠️ Poor naming (unclear variable/method names, abbreviations)
82 - ⚠️ Methods doing multiple things (and/or in method name)
83
84 **Avdi Grimm:**
85 - ⚠️ Law of Demeter violations (chained method calls like `foo.bar.baz.qux`)
86 - ⚠️ Asking instead of telling (lots of getters instead of sending commands)
87
88 **Gary Bernhardt:**
89 - ⚠️ Business logic scattered in imperative shell
90 - ⚠️ Missing value objects (primitives passed around)
91
92 **General:**
93 - ⚠️ Missing documentation for public APIs
94 - ⚠️ Tight coupling between modules
95
96## Output Format
97
98Provide a clear summary with expert attributions:
99
100```
101# Pre-Commit Quality Review
102
103## Files Reviewed
104- file1.rb (23 lines changed)
105- file2.rb (8 lines changed)
106
107## Status: ❌ BLOCK / ✅ PASS / ⚠️ WARNING
108
109### Critical Issues ❌ (must fix before commit)
110
111**Sandi Metz violations:**
112- file1.rb:1 - Missing frozen_string_literal: true
113- file2.rb:15-38 - Method too long (24 lines, max 15)
114
115**Jeremy Evans violations:**
116- file1.rb:42 - Raw SQL string instead of Sequel dataset method
117- file1.rb:50 - Database write without transaction wrapper
118
119**Avdi Grimm violations:**
120- file2.rb:10 - Implicit nil return in public method
121
122### Medium Issues ⚠️ (consider fixing)
123
124**Sandi Metz:**
125- file3.rb:20-32 - Method is 13 lines (consider extracting)
126
127**Kent Beck:**
128- file2.rb:5 - Variable name `x` is unclear (revealing intent)
129
130**Avdi Grimm:**
131- file3.rb:45 - Law of Demeter violation: user.account.settings.theme
132
133### Recommendations
134
1351. Add `frozen_string_literal: true` to file1.rb (Sandi Metz)
1362. Convert raw SQL at file1.rb:42 to Sequel dataset (Jeremy Evans)
1373. Wrap database write at file1.rb:50 in transaction (Jeremy Evans)
1384. Extract file2.rb:15-38 into smaller methods (Sandi Metz)
1395. Return explicit value instead of nil at file2.rb:10 (Avdi Grimm)
1406. Rename `x` to describe what it contains (Kent Beck)
1417. Extract file3.rb:20-32 for better readability (Sandi Metz)
1428. Use tell-don't-ask at file3.rb:45 (Avdi Grimm)
143
144## Suggested Actions
145
146[If BLOCK] Run: git reset HEAD <files> && fix issues && git add <files>
147[If WARNING] Consider fixing before commit or create a follow-up task
148[If PASS] Commit looks good! 🚀
149```
150
151## Exit Behavior
152
153- **Return clear judgment**: BLOCK, WARNING, or PASS
154- **Be specific**: Include file:line references for all issues
155- **Be helpful**: Suggest concrete fixes
156- **Be fast**: Don't over-analyze, focus on obvious problems
157
158## Quick Reference Checklist
159
160For each added/modified line in the diff, scan for:
161
162**Sandi Metz:**
163- [ ] frozen_string_literal at top?
164- [ ] Methods < 15 lines? (warn at 10+)
165- [ ] Classes < 200 lines? (warn at 100+)
166- [ ] No duplicate code?
167- [ ] Parameters <= 3? (warn if more)
168
169**Jeremy Evans:**
170- [ ] Sequel datasets not raw SQL?
171- [ ] DB writes in transactions?
172- [ ] No N+1 queries in loops?
173
174**Kent Beck:**
175- [ ] Nested conditionals <= 3?
176- [ ] Clear, revealing names?
177- [ ] Methods do one thing?
178- [ ] Command-Query Separation?
179
180**Avdi Grimm:**
181- [ ] Null objects instead of nil checks?
182- [ ] Explicit returns (not implicit nil)?
183- [ ] Specific exception classes?
184- [ ] Law of Demeter (max 2 dots)?
185
186**Gary Bernhardt:**
187- [ ] Business logic separate from I/O?
188- [ ] Value objects immutable?
189- [ ] Tests avoid I/O?
190
191## Success Criteria
192
193The review is complete when:
194- All staged Ruby files have been checked
195- Clear BLOCK/WARNING/PASS verdict is given
196- All critical issues have file:line references with expert attribution
197- Concrete fix suggestions are provided with expert rationale