rails-cto-qa
The quality gate. The most important skill in the plugin — every Ruby file must pass its three gates before it's considered done.
What it does
Runs your Ruby changes through three gates, in order:
1. Linting
- Static analysis via
rails-cto-static-analysis— Reek, Flog, and Flay catch code smells, excessive complexity, and duplication before RuboCop runs - RuboCop with aggressive autocorrect (
bundle exec rubocop -A) for style and consistency - No
rubocop:disableescape hatches — fix the code, not the rules
2. Tests
- Runs the tests for the changed files in parallel with coverage enabled
- Requires
subjectto be declared exactly once per test class - Reads
coverage/coverage.json(generated by the SimpleCov JSON formatter) to evaluate per-file coverage - Thresholds: ≥ 90% good, 70–89% acceptable, < 70% insufficient — the skill adds tests until coverage is high enough
3. Code review
- DRY check — three similar lines is a signal to extract
- Dead code removal
- Edge case and error handling check
- Performance review — N+1 queries, missing indexes, heavy work in requests
- Documentation check — every method has a comment explaining why
- Debug statement cleanup — no stray
puts,pp, orbinding.pry - Clarity check — explicit over clever
Nothing is considered done until all three gates pass.
When it triggers
- After creating or modifying any
.rbfile — model, controller, command, service, job, test, anything - When you mention rubocop, lint, style, autocorrect, code quality, code review, QA, or review my code
This skill is mandatory — the CLAUDE.md block installed by rails-cto init enforces it. You cannot ship Ruby changes without it running.
Example
You: Add a cache method to the User model.
Agent: [writes the cache method in app/models/user.rb]
[invokes /rails-cto-qa]
→ runs /rails-cto-static-analysis (Reek/Flog/Flay)
→ runs bundle exec rubocop -A app/models/user.rb
→ runs the user model tests
→ reads coverage/coverage.json → 96% coverage, good
→ reviews the diff for DRY, performance, error handling
→ flags a missing `# Why:` comment on the new method
→ adds the comment
→ re-runs the gate
→ reports: ALL GATES PASS