원클릭으로
architecture
Design Ruby Fast LSP features, understand module responsibilities, apply layer boundaries, and make structural changes.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Design Ruby Fast LSP features, understand module responsibilities, apply layer boundaries, and make structural changes.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Create, update, validate, and maintain Ruby Fast LSP C4 architecture diagrams using LikeC4.
Implement or review error handling patterns in Ruby Fast LSP, including Result, Option, logging, failures, and exception flows.
Optimize Ruby Fast LSP performance, profile latency and memory, benchmark changes, and make performance-critical decisions.
Refactor Ruby Fast LSP modules, extract abstractions, reduce complexity, and preserve test coverage during structural changes.
Release a new version of ruby-fast-lsp. Bumps version in Cargo.toml, commits, tags, and pushes to trigger CI. Use when the user says /release, 'release', 'publish', 'bump version', 'cut a release', or 'new version'.
Review Ruby Fast LSP code changes and PRs using TigerStyle principles, project standards, and correctness checks.
| name | architecture |
| description | Design Ruby Fast LSP features, understand module responsibilities, apply layer boundaries, and make structural changes. |
Use this skill when designing new features, understanding module responsibilities, or making structural changes to the Ruby Fast LSP project. Provides guidance on the 3-layer architecture, module boundaries, and dependency rules. Triggers: architecture, design, module structure, dependencies, layers, new feature, refactoring structure.
┌─────────────────────────────────────────────────────────────┐
│ LAYER 1: API Layer │
│ server.rs + handlers/ │
│ - LSP protocol handling │
│ - Request/response routing │
│ - Thin: delegates to capabilities │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ LAYER 2: Service Layer │
│ query/ + capabilities/ │
│ - Business logic │
│ - Feature implementations │
│ - IndexQuery as unified interface │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ LAYER 3: Data Layer │
│ indexer/ + types/ │
│ - Symbol storage (RubyIndex) │
│ - Core types (FQN, RubyType) │
│ - Two-phase indexing │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ FOUNDATION: Analysis Layer │
│ analyzer_prism/ + inferrer/ │
│ - AST traversal │
│ - Type inference │
│ - CFG-based analysis │
└─────────────────────────────────────────────────────────────┘
handlers/ ──────► capabilities/
│
▼
query/
│
┌───────────┼───────────┐
▼ ▼ ▼
indexer/ analyzer_prism/ inferrer/
│ │ │
└───────────┼───────────┘
▼
types/
Purpose: Route LSP requests/notifications to appropriate handlers.
Files:
request.rs - Handle LSP requests (goto, hover, completion, etc.)notification.rs - Handle LSP notifications (didOpen, didChange, etc.)Rules:
// GOOD: Thin handler
pub async fn handle_goto_definition(
server: &RubyLanguageServer,
params: GotoDefinitionParams,
) -> Result<Option<GotoDefinitionResponse>> {
let uri = params.text_document_position_params.text_document.uri;
let position = params.text_document_position_params.position;
definition::goto_definition(server, &uri, position).await
}
Purpose: Implement LSP features using query layer.
Modules:
completion/ - Code completiondefinition/ - Go-to-definitionhover/ - Hover informationreferences/ - Find referencesinlay_hints/ - Type hintscode_lens/ - Code lensesdiagnostics/ - Error reportingRules:
// GOOD: Uses IndexQuery
pub async fn goto_definition(
server: &RubyLanguageServer,
uri: &Url,
position: Position,
) -> Option<GotoDefinitionResponse> {
let query = IndexQuery::new(&server.index, uri);
query.find_definitions_at_position(position)
}
Purpose: Unified interface for all index queries. Single point of access.
Key Type: IndexQuery
pub struct IndexQuery<'a> {
index: &'a RubyIndex,
document: Option<&'a RubyDocument>,
}
impl IndexQuery<'_> {
// Navigation
pub fn find_definitions_at_position(&self, pos: Position) -> Vec<Location>;
pub fn find_references_at_position(&self, pos: Position) -> Vec<Location>;
// Type information
pub fn get_hover_at_position(&self, pos: Position) -> Option<Hover>;
pub fn resolve_type_at_position(&self, pos: Position) -> Option<RubyType>;
// Completion
pub fn get_completions_at_position(&self, pos: Position) -> Vec<CompletionItem>;
}
Rules:
Purpose: Symbol storage and retrieval.
Key Components:
RubyIndex - Central in-memory symbol storeFileProcessor - Process single filesCoordinator - Orchestrate workspace indexingTwo-Phase Indexing Protocol:
Phase 1: Build Definitions
┌─────────────────────────────────────┐
│ For each file: │
│ 1. Parse with Prism │
│ 2. Extract class/module/method │
│ 3. Store definitions in index │
└─────────────────────────────────────┘
│
▼
Phase 2: Resolve References
┌─────────────────────────────────────┐
│ For each file: │
│ 1. Resolve constant references │
│ 2. Build inheritance graph │
│ 3. Link method calls to defs │
└─────────────────────────────────────┘
Rules:
Purpose: Ruby code analysis via Prism parser.
Key Types:
RubyPrismAnalyzer - Main analyzerIdentifier - Parsed identifier with positionMethodReceiver - Receiver type for method callsRules:
Purpose: Type inference engine.
Key Components:
RubyType - Type representationTypeQuery - Query types at positionscfg/ - Control flow graph for type narrowingRules:
Purpose: Core type definitions used everywhere.
Key Types:
FullyQualifiedName (FQN) - Validated symbol namesRubyConstant - Validated constant namesRubyMethod - Validated method namesLocation, Position, Range - LSP primitivesRules:
Ustr for interned stringssrc/capabilities/my_feature/
├── mod.rs # Main entry point
└── helpers.rs # Optional helpers
// src/capabilities/my_feature/mod.rs
use crate::query::IndexQuery;
pub async fn handle_my_feature(
server: &RubyLanguageServer,
params: MyFeatureParams,
) -> Option<MyFeatureResponse> {
let query = IndexQuery::new(&server.index, ¶ms.uri);
// Use query methods
let result = query.find_something(params.position)?;
Some(result.into())
}
// src/handlers/request.rs
MyFeatureRequest::METHOD => {
let params: MyFeatureParams = serde_json::from_value(params)?;
let result = my_feature::handle_my_feature(&server, params).await;
Ok(serde_json::to_value(result)?)
}
// src/server.rs - in initialize()
capabilities.my_feature_provider = Some(MyFeatureOptions::default());
When capabilities need new query patterns, add to IndexQuery:
// src/query/mod.rs
impl IndexQuery<'_> {
/// Find all symbols matching the given pattern.
///
/// # Example
/// ```
/// let symbols = query.find_symbols_matching("User*");
/// ```
pub fn find_symbols_matching(&self, pattern: &str) -> Vec<Symbol> {
// Implementation using self.index
}
}
| Module | Target | Max | Current Status |
|---|---|---|---|
| Handler files | 50 lines | 100 lines | OK |
| Capability entry | 100 lines | 300 lines | Some exceed |
| Query methods | 50 lines | 100 lines | OK |
| Indexer files | 200 lines | 500 lines | coordinator.rs exceeds |
| Analyzer | 500 lines | 800 lines | mod.rs exceeds (2420) |
When making structural changes, document:
Example:
## ADR-001: Unified Query Layer
### Context
Query logic was scattered across capabilities, leading to duplication.
### Decision
Create IndexQuery as single entry point for all index queries.
### Consequences
- (+) Consistent API across features
- (+) Easier to add new query patterns
- (-) One more layer of indirection