context compilation with cclsp

Context Compilation with cclsp + Sorbet

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "context compilation with cclsp" with this command: npx skills add kaakati/rails-enterprise-dev/kaakati-rails-enterprise-dev-context-compilation-with-cclsp

Context Compilation with cclsp + Sorbet

This skill provides patterns for LSP-powered context extraction and type-safe code generation using cclsp MCP tools, Solargraph, and Sorbet.

  1. Tool Stack Overview

1.1 cclsp MCP Bridge

The cclsp MCP server provides Claude Code access to Language Server Protocol functionality:

Tool Purpose Use Case

mcp__cclsp__find_definition

Find symbol definitions Locate where methods/classes are defined

mcp__cclsp__find_references

Find all references Discover symbol usage patterns

mcp__cclsp__get_diagnostics

Get errors/warnings Validate code before execution

mcp__cclsp__rename_symbol

Rename symbols Safe refactoring

mcp__cclsp__rename_symbol_strict

Rename at position Precise symbol renaming

mcp__cclsp__restart_server

Restart LSP Recover from errors

1.2 Solargraph (Ruby LSP)

Solargraph provides Ruby-specific language intelligence:

  • Method completion: Know what methods exist on objects

  • Go to definition: Jump to class/method definitions

  • Hover documentation: Inline YARD documentation

  • Diagnostics: Syntax errors, undefined methods

  • Workspace symbols: Search all symbols in project

Configuration (.solargraph.yml ):

include:

  • "**/*.rb" exclude:
  • spec/**/*
  • test/**/*
  • vendor/**/* reporters:
  • rubocop
  • require_not_found plugins: [] require_paths: [] domains: [] max_files: 5000

1.3 Sorbet (Type Checker)

Sorbet provides static type checking for Ruby:

  • Static analysis: Catch type errors at compile time

  • Runtime checking: Verify types during execution

  • Gradual typing: Adopt incrementally with # typed: sigils

  • IDE integration: LSP support via Sorbet Language Server

Type Sigils:

typed: ignore # Skip this file

typed: false # Only syntax errors

typed: true # Check types

typed: strict # Require signatures

typed: strong # No T.untyped

Common Commands:

Type check entire project

bundle exec srb tc

Type check specific file

bundle exec srb tc app/models/user.rb

Initialize Sorbet

bundle exec srb init

Generate RBI files

bundle exec tapioca init bundle exec tapioca dsl bundle exec tapioca gems

1.4 Supporting Tools

Tool Purpose Integration

parser gem AST analysis Deep code structure analysis

ripper Built-in Ruby parser Fallback parsing, always available

YARD Documentation Solargraph uses YARD for docs

Tapioca RBI generation Generate type signatures for gems

  1. cclsp Tool Reference

2.1 find_definition

Find where a symbol is defined:

Usage Pattern

mcp__cclsp__find_definition( file_path: "app/services/payment_service.rb", symbol_name: "PaymentGateway", symbol_kind: "class" # optional: class, method, module )

Returns

{ "definitions": [ { "file": "app/gateways/payment_gateway.rb", "line": 5, "column": 1, "symbol": "PaymentGateway" } ] }

Common symbol_kind values:

  • class

  • Class definitions

  • module

  • Module definitions

  • method

  • Instance methods

  • function

  • Module/class methods

  • variable

  • Local/instance variables

  • constant

  • Constants

2.2 find_references

Find all usages of a symbol:

Usage Pattern

mcp__cclsp__find_references( file_path: "app/models/user.rb", symbol_name: "authenticate", include_declaration: true )

Returns

{ "references": [ { "file": "app/models/user.rb", "line": 45, "column": 3, "context": "def authenticate(password)" }, { "file": "app/controllers/sessions_controller.rb", "line": 12, "column": 8, "context": "if user.authenticate(params[:password])" } ] }

2.3 get_diagnostics

Get errors and warnings for a file:

Usage Pattern

mcp__cclsp__get_diagnostics( file_path: "app/services/order_service.rb" )

Returns

{ "diagnostics": [ { "severity": 1, # 1=Error, 2=Warning, 3=Info, 4=Hint "message": "Undefined method `foo' for OrderService", "range": { "start": {"line": 25, "character": 4}, "end": {"line": 25, "character": 7} }, "source": "solargraph" } ] }

Severity Levels:

  • 1

  • Error (must fix)

  • 2

  • Warning (should investigate)

  • 3

  • Information (good to know)

  • 4

  • Hint (suggestions)

2.4 rename_symbol

Rename a symbol across the codebase:

Preview changes (dry_run)

mcp__cclsp__rename_symbol( file_path: "app/models/user.rb", symbol_name: "full_name", new_name: "display_name", dry_run: true )

Apply changes

mcp__cclsp__rename_symbol( file_path: "app/models/user.rb", symbol_name: "full_name", new_name: "display_name" )

  1. Interface Extraction Patterns

3.1 Extract Class Interface

Extract public interface from a class:

Pattern: Interface Extraction

def extract_interface(class_name, file_path)

1. Find class definition

definition = mcp__cclsp__find_definition( file_path: file_path, symbol_name: class_name, symbol_kind: "class" )

2. Read the class file

class_content = Read(definition.file)

3. Extract public methods

public_methods = class_content.scan(/^\s*def\s+(\w+)/).flatten

4. For each method, find references to understand usage

method_interfaces = public_methods.map do |method| refs = mcp__cclsp__find_references( file_path: definition.file, symbol_name: method )

{
  name: method,
  defined_at: "#{definition.file}:#{method_line}",
  usage_count: refs.count,
  callers: refs.map { |r| r.file }.uniq
}

end

method_interfaces end

3.2 Extract Dependency Graph

Build a dependency graph for a class:

Pattern: Dependency Graph

def build_dependency_graph(entry_class, entry_file) graph = { nodes: [], edges: [] } visited = Set.new queue = [[entry_class, entry_file]]

while queue.any? class_name, file_path = queue.shift next if visited.include?(class_name) visited.add(class_name)

# Add node
graph[:nodes] << { name: class_name, file: file_path }

# Find references to other classes
class_content = Read(file_path)
constants = class_content.scan(/([A-Z][A-Za-z0-9]+)/).flatten.uniq

constants.each do |const|
  definition = mcp__cclsp__find_definition(
    file_path: file_path,
    symbol_name: const,
    symbol_kind: "class"
  )

  if definition && !visited.include?(const)
    graph[:edges] << { from: class_name, to: const }
    queue << [const, definition.file]
  end
end

end

graph end

3.3 Per-Task Interface Extraction

Extract interfaces relevant to a specific task:

Pattern: Task-Specific Interface Extraction

def compile_task_context(task) context = { interfaces: [], vocabulary: [], cclsp_enhanced: true }

1. Identify files mentioned in task

target_files = task[:files] || []

2. For each file, extract interfaces

target_files.each do |file| # Get diagnostics first (validates file exists) diagnostics = mcp__cclsp__get_diagnostics(file_path: file)

# Find all symbols in file
symbols = extract_file_symbols(file)

# For each symbol, get definition and references
symbols.each do |symbol|
  definition = mcp__cclsp__find_definition(
    file_path: file,
    symbol_name: symbol[:name],
    symbol_kind: symbol[:kind]
  )

  references = mcp__cclsp__find_references(
    file_path: file,
    symbol_name: symbol[:name]
  )

  context[:interfaces] << {
    symbol: symbol[:name],
    kind: symbol[:kind],
    file: file,
    definition: definition,
    references: references.count,
    signature: extract_signature(definition)
  }
end

end

context end

  1. Vocabulary Building Patterns

4.1 Project Vocabulary Extraction

Build a vocabulary of project-specific terms:

Pattern: Project Vocabulary

def build_project_vocabulary vocabulary = { models: [], services: [], controllers: [], patterns: [], domain_terms: [] }

1. Scan models

Dir["app/models/**/*.rb"].each do |file| content = Read(file)

# Extract class name
if content =~ /class\s+(\w+)/
  model_name = $1
  vocabulary[:models] << {
    name: model_name,
    file: file,
    associations: content.scan(/(?:has_many|belongs_to|has_one)\s+:(\w+)/).flatten,
    scopes: content.scan(/scope\s+:(\w+)/).flatten,
    validations: content.scan(/validates\s+:(\w+)/).flatten
  }
end

end

2. Scan services

Dir["app/services/**/*.rb"].each do |file| content = Read(file)

if content =~ /class\s+(\w+)/
  service_name = $1
  vocabulary[:services] << {
    name: service_name,
    file: file,
    public_methods: content.scan(/^\s*def\s+(\w+)/).flatten,
    dependencies: extract_dependencies(content)
  }
end

end

3. Extract domain terms from comments and names

all_files = Dir["app/**/*.rb"] all_files.each do |file| content = Read(file)

# Extract from comments
comments = content.scan(/#\s*(.+)$/).flatten

# Extract from class/method names
identifiers = content.scan(/(?:class|def|module)\s+(\w+)/).flatten

# Add unique terms
terms = (comments + identifiers).map(&:downcase).uniq
vocabulary[:domain_terms].concat(terms)

end

vocabulary[:domain_terms].uniq! vocabulary end

4.2 Symbol Vocabulary for Generation

Build vocabulary to guide code generation:

Pattern: Generation Vocabulary

def build_generation_vocabulary(target_file) vocab = { available_classes: [], available_methods: [], common_patterns: [], naming_conventions: [] }

1. Find all classes in the project

Dir["app/**/*.rb"].each do |file| content = Read(file) classes = content.scan(/class\s+(\w+)/).flatten vocab[:available_classes].concat(classes) end

2. For the target file's directory, find common patterns

dir = File.dirname(target_file) sibling_files = Dir["#{dir}/*.rb"]

sibling_files.each do |file| content = Read(file)

# Extract method patterns
methods = content.scan(/def\s+(\w+)/).flatten
vocab[:available_methods].concat(methods)

# Extract common patterns
if content.include?("Result.success")
  vocab[:common_patterns] << "Result monad"
end
if content.include?("ApplicationService")
  vocab[:common_patterns] << "ApplicationService inheritance"
end

end

vocab[:available_classes].uniq! vocab[:available_methods].uniq! vocab[:common_patterns].uniq!

vocab end

  1. Guardian Validation Patterns

5.1 Pre-Generation Validation

Validate before generating code:

Pattern: Pre-Generation Check

def pre_generation_validate(target_file) validation = { passed: true, issues: [] }

1. Check if cclsp is available

begin mcp__cclsp__get_diagnostics(file_path: "Gemfile") rescue validation[:issues] << "cclsp not available - skipping LSP validation" return validation end

2. Check existing file for errors

if File.exist?(target_file) diagnostics = mcp__cclsp__get_diagnostics(file_path: target_file) errors = diagnostics.select { |d| d[:severity] == 1 }

if errors.any?
  validation[:passed] = false
  validation[:issues] &#x3C;&#x3C; "Existing file has #{errors.count} errors - fix first"
end

end

3. Check parent class exists

(would need to parse generation template)

validation end

5.2 Post-Generation Validation (Guardian)

Validate after generating code:

Pattern: Guardian Validation

def guardian_validate(file_path) result = { passed: true, errors: [], warnings: [], suggestions: [] }

1. cclsp diagnostics (Solargraph)

diagnostics = mcp__cclsp__get_diagnostics(file_path: file_path)

diagnostics.each do |d| case d[:severity] when 1 # Error result[:passed] = false result[:errors] << { line: d[:range][:start][:line], message: d[:message], source: d[:source] } when 2 # Warning result[:warnings] << { line: d[:range][:start][:line], message: d[:message] } when 3, 4 # Info/Hint result[:suggestions] << { line: d[:range][:start][:line], message: d[:message] } end end

2. Sorbet type checking (if available)

sorbet_output = bundle exec srb tc #{file_path} 2>&#x26;1 sorbet_errors = sorbet_output.lines.select { |l| l.start_with?(file_path) }

sorbet_errors.each do |error| if error =~ /#{file_path}:(\d+):\s*(.+)/ result[:passed] = false result[:errors] << { line: $1.to_i, message: $2, source: "sorbet" } end end

result end

5.3 Generate-Validate-Execute-Verify Cycle

Full implementation cycle with Guardian:

Pattern: Full Implementation Cycle

def implement_with_guardian(file_path, specification, max_attempts: 3) attempt = 0

loop do attempt += 1 puts "Attempt #{attempt}/#{max_attempts}: #{file_path}"

# 1. GENERATE
puts "  1/4 GENERATE: Writing code..."
generate_code(file_path, specification)

# 2. VALIDATE (Guardian)
puts "  2/4 VALIDATE: Running Guardian..."
validation = guardian_validate(file_path)

unless validation[:passed]
  puts "  Guardian found #{validation[:errors].count} errors"

  if attempt >= max_attempts
    return { success: false, reason: "Max attempts reached" }
  end

  # Apply fixes and retry
  apply_guardian_fixes(file_path, validation[:errors])
  next
end

# 3. EXECUTE
puts "  3/4 EXECUTE: Running tests..."
test_result = run_tests_for_file(file_path)

unless test_result[:passed]
  puts "  Tests failed: #{test_result[:failures].count} failures"

  if attempt >= max_attempts
    return { success: false, reason: "Tests failed" }
  end

  # Analyze failures and retry
  analyze_and_fix_tests(file_path, test_result[:failures])
  next
end

# 4. VERIFY
puts "  4/4 VERIFY: Final check..."
final_check = final_verification(file_path)

return { success: true, attempts: attempt, verification: final_check }

end end

def apply_guardian_fixes(file_path, errors)

Group errors by type

undefined_methods = errors.select { |e| e[:message].include?("Undefined method") } type_errors = errors.select { |e| e[:source] == "sorbet" } syntax_errors = errors.select { |e| e[:message].include?("syntax") }

Apply targeted fixes

if undefined_methods.any? # Find correct method names using find_references fix_undefined_methods(file_path, undefined_methods) end

if type_errors.any? # Add type signatures or fix type mismatches fix_type_errors(file_path, type_errors) end

if syntax_errors.any? # Fix syntax issues fix_syntax_errors(file_path, syntax_errors) end end

  1. Sorbet Integration Patterns

6.1 Type Signature Extraction

Extract Sorbet type signatures from a file:

Pattern: Sorbet Signature Extraction

def extract_sorbet_signatures(file_path) content = Read(file_path) signatures = []

Find sig blocks

content.scan(/sig\s*{([^}]+)}/) do |sig_content| sig = sig_content[0]

# Parse params
params = {}
sig.scan(/params\(([^)]+)\)/) do |params_str|
  params_str[0].split(",").each do |param|
    name, type = param.strip.split(":").map(&#x26;:strip)
    params[name] = type
  end
end

# Parse returns
returns = nil
if sig =~ /returns\(([^)]+)\)/
  returns = $1.strip
end

signatures &#x3C;&#x3C; { params: params, returns: returns }

end

signatures end

6.2 Type-Guided Generation

Use type information to guide code generation:

Pattern: Type-Guided Generation

def generate_with_types(file_path, method_spec)

1. Look up existing type signatures in project

similar_methods = find_similar_methods(method_spec[:name])

2. Infer expected types from callers

references = mcp__cclsp__find_references( file_path: file_path, symbol_name: method_spec[:name] )

inferred_types = infer_types_from_usage(references)

3. Generate with explicit types

signature = <<~RUBY sig { params(#{format_params(inferred_types[:params])}).returns(#{inferred_types[:returns]}) } def #{method_spec[:name]}(#{format_args(method_spec[:args])}) # Implementation end RUBY

signature end

6.3 Sorbet Strictness Levels

Apply appropriate Sorbet strictness:

Pattern: Sorbet Strictness Selection

def select_sorbet_strictness(file_path)

New files: start with # typed: true

Critical business logic: use # typed: strict

Generated code: use # typed: false initially

case file_path when /app/services// "# typed: strict" # Services should have strong types when /app/models// "# typed: true" # Models can start with basic types when /app/controllers// "# typed: false" # Controllers often have complex types when /lib// "# typed: strict" # Library code should be well-typed else "# typed: true" # Default to basic type checking end end

  1. Graceful Degradation

7.1 Tool Availability Check

Check which tools are available:

Pattern: Availability Check

check_tool_availability() { local availability="{}"

Check cclsp

if mcp__cclsp__get_diagnostics --file_path "Gemfile" 2>/dev/null; then availability=$(echo "$availability" | jq '.cclsp = true') else availability=$(echo "$availability" | jq '.cclsp = false') fi

Check Solargraph

if gem list solargraph -i &>/dev/null; then availability=$(echo "$availability" | jq '.solargraph = true') else availability=$(echo "$availability" | jq '.solargraph = false') fi

Check Sorbet

if bundle exec srb --version &>/dev/null || gem list sorbet -i &>/dev/null; then availability=$(echo "$availability" | jq '.sorbet = true') else availability=$(echo "$availability" | jq '.sorbet = false') fi

Check parser gem

if gem list parser -i &>/dev/null; then availability=$(echo "$availability" | jq '.parser = true') else availability=$(echo "$availability" | jq '.parser = false') fi

echo "$availability" }

7.2 Fallback Strategies

Fallback when tools are unavailable:

Pattern: Graceful Degradation

def compile_context_with_fallback(task) availability = check_tool_availability

context = { cclsp_enhanced: false, interfaces: [], vocabulary: [], fallback_used: [] }

Primary: Use cclsp

if availability[:cclsp] context[:cclsp_enhanced] = true context[:interfaces] = extract_interfaces_with_cclsp(task) else # Fallback: Use grep and AST parsing context[:fallback_used] << "grep for interface extraction" context[:interfaces] = extract_interfaces_with_grep(task) end

Primary: Use Sorbet for type info

if availability[:sorbet] context[:type_info] = extract_type_info_with_sorbet(task) else # Fallback: Use YARD comments context[:fallback_used] << "YARD for type hints" context[:type_info] = extract_type_info_from_yard(task) end

Primary: Use parser gem

if availability[:parser] context[:ast_analysis] = analyze_with_parser(task) else # Fallback: Use ripper (always available) context[:fallback_used] << "ripper for AST" context[:ast_analysis] = analyze_with_ripper(task) end

context end

def extract_interfaces_with_grep(task) interfaces = []

task[:files].each do |file| # Use grep to find method definitions methods = grep -n "def " #{file} | head -50.lines

methods.each do |line|
  if line =~ /^(\d+):\s*def\s+(\w+)/
    interfaces &#x3C;&#x3C; {
      symbol: $2,
      kind: "method",
      file: file,
      line: $1.to_i
    }
  end
end

end

interfaces end

7.3 Partial Feature Mode

Enable features based on available tools:

Pattern: Feature Flags

def determine_enabled_features features = { lsp_diagnostics: false, type_checking: false, smart_refactoring: false, vocabulary_building: true, # Always available interface_extraction: true # Always available (grep fallback) }

availability = check_tool_availability

if availability[:cclsp] features[:lsp_diagnostics] = true features[:smart_refactoring] = true end

if availability[:sorbet] features[:type_checking] = true end

features end

  1. Working Memory Integration

8.1 Store Compiled Context

Store context for implementation phase:

Pattern: Store Compiled Context

def store_compiled_context(task_id, context) memory_entry = { timestamp: Time.now.utc.iso8601, agent: "context-compiler", knowledge_type: "compiled_context", key: "task.#{task_id}.context", value: context, confidence: "verified" }

Write to working memory file

File.open(".claude/reactree-memory.jsonl", "a") do |f| f.puts(memory_entry.to_json) end end

8.2 Read Compiled Context

Read context during implementation:

Pattern: Read Compiled Context

def read_compiled_context(task_id) memory_file = ".claude/reactree-memory.jsonl" return nil unless File.exist?(memory_file)

Read most recent context for task

context = nil

File.readlines(memory_file).reverse_each do |line| entry = JSON.parse(line)

if entry["key"] == "task.#{task_id}.context"
  context = entry["value"]
  break
end

end

context end

  1. Quick Reference

Command Cheatsheet

Solargraph

gem install solargraph solargraph config # Generate .solargraph.yml solargraph socket --port 7658 # Start language server

Sorbet

gem install sorbet sorbet-runtime bundle exec srb init # Initialize Sorbet bundle exec srb tc # Type check project bundle exec srb tc app/models/ # Type check directory bundle exec srb tc --ignore=sorbet/ # Ignore directory

Tapioca (RBI generation)

gem install tapioca bundle exec tapioca init # Initialize bundle exec tapioca gems # Generate gem RBIs bundle exec tapioca dsl # Generate DSL RBIs bundle exec tapioca annotations # Sync annotations

parser gem

gem install parser ruby -rparser/current -e 'p Parser::CurrentRuby.parse("def foo; end")'

cclsp MCP Quick Reference

Find where a method is defined

mcp__cclsp__find_definition( file_path: "app/models/user.rb", symbol_name: "authenticate" )

Find all usages of a class

mcp__cclsp__find_references( file_path: "app/services/payment_service.rb", symbol_name: "PaymentService" )

Check file for errors

mcp__cclsp__get_diagnostics( file_path: "app/services/order_service.rb" )

Rename symbol (preview)

mcp__cclsp__rename_symbol( file_path: "app/models/user.rb", symbol_name: "old_method", new_name: "new_method", dry_run: true )

Guardian Validation Quick Reference

Full validation cycle

def validate_file(file_path)

1. cclsp diagnostics

diagnostics = mcp__cclsp__get_diagnostics(file_path: file_path) errors = diagnostics.select { |d| d[:severity] == 1 }

2. Sorbet check

sorbet_output = bundle exec srb tc #{file_path} 2>&#x26;1 sorbet_errors = sorbet_output.lines.count { |l| l.start_with?(file_path) }

3. Combined result

{ passed: errors.empty? && sorbet_errors == 0, lsp_errors: errors.count, sorbet_errors: sorbet_errors } end

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

flutter conventions & best practices

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

getx state management patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

ruby oop patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

viewcomponents specialist

No summary provided by upstream source.

Repository SourceNeeds Review