Comprehensive code quality validation using Solargraph, Sorbet, and Rubocop for A+ Rails code. Trigger keywords: quality gates, validation, solargraph, sorbet, rubocop, type checking, linting, code quality, static analysis
Runs Solargraph diagnostics, Sorbet type checks, and Rubocop linting to validate Ruby code quality. Triggers after code edits or when you request validation.
/plugin marketplace add Kaakati/rails-enterprise-dev/plugin install reactree-rails-dev@manifest-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
This skill provides patterns for comprehensive code quality validation using three complementary tools: Solargraph (LSP diagnostics), Sorbet (type checking), and Rubocop (style enforcement).
Purpose: Language server providing IDE-like features and diagnostics
Setup:
gem install solargraph
solargraph config # Generates .solargraph.yml
Key Features:
Diagnostics Patterns:
NoMethodError detectioncclsp Integration:
# Agents use cclsp MCP tools
mcp__cclsp__get_diagnostics file_path="app/models/user.rb"
# Returns: errors, warnings, hints for the file
Configuration (.solargraph.yml):
include:
- "**/*.rb"
exclude:
- spec/**/*
- test/**/*
- vendor/**/*
reporters:
- rubocop
- require_not_found
plugins: []
require_paths: []
domains: []
max_files: 5000
Purpose: Static type checker for Ruby with gradual typing
Setup:
# Add to Gemfile
gem 'sorbet'
gem 'sorbet-runtime'
# Initialize
bundle exec srb init
# Generate RBI files for gems
bundle exec tapioca init
bundle exec tapioca gems
Gradual adoption through file-level type checking levels:
# typed: ignore # Skip this file entirely
# typed: false # Only check syntax errors
# typed: true # Check types, infer missing signatures
# typed: strict # Require explicit signatures
# typed: strong # No T.untyped allowed
Basic Signature:
sig { params(name: String).returns(User) }
def find_by_name(name)
User.where(name: name).first
end
Void Methods:
sig { params(user: User).void }
def send_notification(user)
Mailer.deliver(user.email)
end
Nilable Types:
sig { params(id: Integer).returns(T.nilable(User)) }
def find_user(id)
User.find_by(id: id) # May return nil
end
Arrays and Hashes:
sig { params(items: T::Array[String]).returns(T::Hash[String, Integer]) }
def count_items(items)
items.tally
end
Class Methods:
class << self
sig { returns(T::Array[User]) }
def active_users
where(active: true).to_a
end
end
Purpose: Ruby static code analyzer and formatter
Setup:
gem install rubocop
rubocop --init # Generates .rubocop.yml
# Fix safe offenses automatically
rubocop -a
# Fix all offenses (use with caution)
rubocop -A
# Fix specific file
rubocop -a app/models/user.rb
# Check without fixing
rubocop --fail-level error --format simple app/models/user.rb
Line Length (default: 120):
# Bad
def very_long_method_name_that_exceeds_the_maximum_allowed_line_length_for_ruby_code_according_to_rubocop_standards
# Good
def descriptive_method_name
# Implementation
end
Frozen String Literal:
# Add to top of file
# frozen_string_literal: true
Inconsistent Indentation:
# Bad
def method
puts "inconsistent"
puts "indentation"
end
# Good
def method
puts "consistent"
puts "indentation"
end
Trailing Whitespace:
# Bad
def method
puts "hello"
end
# Good
def method
puts "hello"
end
.rubocop.yml):AllCops:
TargetRubyVersion: 3.2
NewCops: enable
Exclude:
- 'db/schema.rb'
- 'vendor/**/*'
- 'node_modules/**/*'
Layout/LineLength:
Max: 120
Style/Documentation:
Enabled: false # Allow missing class docs
Metrics/MethodLength:
Max: 20
Metrics/AbcSize:
Max: 20
Runs after each implementation layer (models, services, components):
validate-implementation.sh Workflow:
Check Tool Availability
check_tool_available solargraph # → true/false
check_tool_available sorbet # → true/false
check_tool_available rubocop # → true/false
Solargraph Diagnostics
for file in $FILES; do
solargraph check "$file" # Get diagnostics
# Check for errors
done
Sorbet Type Check (typed files only)
# Filter to typed files
typed_files=$(grep -l "# typed:" $FILES)
# Run type check
bundle exec srb tc $typed_files
Rubocop Style Check
# Fail on warnings (blocking mode)
rubocop --fail-level warning --format simple $FILES
Exit Based on Validation Level
Runs after Phase 4 for comprehensive type safety:
guardian-validation.sh Workflow:
Collect Modified Files
FILES=$(bd show $FEATURE_ID | grep -oE "app/[a-z_/]+\.rb")
Run Sorbet Type Check
bundle exec srb tc $FILES
Analyze Errors (if any)
Attempt Auto-Fix (simple cases)
# Add default signature
sig { returns(T.untyped) }
def method_name
# ...
end
Re-validate (max 3 iterations)
Block or Pass
Hook: PreToolUse (before Edit tool)
# Check syntax before applying edit
echo "$NEW_CONTENT" | ruby -c
# If typed file, warn about Sorbet validation
if grep -q "# typed:" "$FILE_PATH"; then
echo "ℹ️ Sorbet validation will run post-edit"
fi
Hook: PostToolUse (after Write tool)
# Syntax check (always)
ruby -c "$FILE_PATH"
# Rubocop (if available)
rubocop --fail-level error "$FILE_PATH"
# Sorbet (if typed)
if grep -q "# typed:" "$FILE_PATH"; then
bundle exec srb tc "$FILE_PATH"
fi
Undefined Method:
Error: Method 'email' is not defined on User
Fix: Define the method or add to class
def email
# ...
end
Unresolved Constant:
Error: Constant 'PaymentService' not found
Fix: Require the file or fix namespace
require_relative 'payment_service'
Missing Signature:
Error: Method does not have a `sig`
Fix:
sig { params(name: String).returns(User) }
def find_by_name(name)
# ...
end
Type Mismatch:
Error: Expected String but found Integer
Fix: Convert type or update signature
name.to_s # Convert Integer to String
Undefined Method on Typed Value:
Error: Method `email` does not exist on `T.untyped`
Fix: Add type annotation
sig { params(user: User).void } # Now user has type
def send_email(user)
user.email # Safe - user is typed as User
end
Style/FrozenStringLiteralComment:
Fix: Add to top of file
# frozen_string_literal: true
Layout/LineLength:
Fix: Break long lines
# Bad
very_long_method_call_with_many_parameters(param1, param2, param3, param4)
# Good
very_long_method_call_with_many_parameters(
param1,
param2,
param3,
param4
)
Phase 1: Start with Rubocop
# .rubocop.yml - relaxed rules
Metrics/MethodLength:
Max: 30 # Increase limits initially
Phase 2: Add Solargraph for diagnostics
solargraph check app/models/*.rb # Check specific directories
Phase 3: Introduce Sorbet with # typed: false
# typed: false # Minimal checking
class User
# No signatures required yet
end
Phase 4: Gradually upgrade to # typed: true
# typed: true # Type inference enabled
class User
sig { params(name: String).returns(User) } # Add signatures
def self.find_by_name(name)
# ...
end
end
Focus on new files first:
New files → # typed: true (type-safe from start)
Old files → # typed: false (legacy, upgrade gradually)
Core files → # typed: strict (critical paths)
Run quality gates in CI:
# .github/workflows/quality.yml
- name: Rubocop
run: bundle exec rubocop
- name: Sorbet
run: bundle exec srb tc
- name: Solargraph
run: solargraph check app/**/*.rb
---
enabled: true
quality_gates_enabled: true
guardian_enabled: true
validation_level: blocking # blocking, warning, advisory
guardian_max_iterations: 3
---
include:
- "**/*.rb"
exclude:
- spec/**/*
- test/**/*
- vendor/**/*
- db/schema.rb
reporters:
- rubocop
- require_not_found
max_files: 5000
AllCops:
TargetRubyVersion: 3.2
NewCops: enable
Exclude:
- 'db/schema.rb'
- 'vendor/**/*'
Layout/LineLength:
Max: 120
Style/FrozenStringLiteralComment:
Enabled: true
EnforcedStyle: always
--dir
.
--ignore=/vendor/
--ignore=/tmp/
# Rebuild index
solargraph clear
solargraph download-core
# Check configuration
solargraph config
# Regenerate RBI files
bundle exec tapioca gems
# Check Sorbet version
bundle exec srb --version
# Run with verbose output
bundle exec srb tc --verbose
# Disable specific cop for line
# rubocop:disable Style/FrozenStringLiteralComment
code_here
# rubocop:enable Style/FrozenStringLiteralComment
# Disable for file
# rubocop:disable all
Code Quality Gates provide three layers of validation:
Integration Points:
Gradual Adoption:
Result: A+ type-safe, well-styled Rails code with comprehensive quality validation.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.