원클릭으로
tigerstyle
Apply TigerBeetle-inspired Ruby Fast LSP code quality rules for safety, performance, invariants, and maintainability.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Apply TigerBeetle-inspired Ruby Fast LSP code quality rules for safety, performance, invariants, and maintainability.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Design Ruby Fast LSP features, understand module responsibilities, apply layer boundaries, and make structural changes.
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'.
| name | tigerstyle |
| description | Apply TigerBeetle-inspired Ruby Fast LSP code quality rules for safety, performance, invariants, and maintainability. |
Use this skill when writing new code, reviewing code, or refactoring existing code in the Ruby Fast LSP project. Enforces TigerBeetle-inspired coding standards for safety, performance, and maintainability. Triggers: writing code, code quality, style guide, best practices, coding standards.
Priority order: Safety > Performance > Developer Experience
Simplicity and elegance require hard work and discipline. Invest upfront design effort to prevent expensive production problems.
No function should exceed 70 lines. This prevents cognitive overload and forces proper decomposition.
If a function exceeds 70 lines:
// BAD: 150-line function
fn process_document(doc: &Document) -> Result<()> {
// ... 150 lines of mixed concerns
}
// GOOD: Decomposed
fn process_document(doc: &Document) -> Result<()> {
let parsed = parse_content(doc)?;
let indexed = index_symbols(&parsed)?;
resolve_references(&indexed)?;
Ok(())
}
Assert both positive space (expected behavior) and negative space (invalid states).
fn find_definition(index: &Index, fqn: &Fqn) -> Option<Location> {
assert!(!fqn.is_empty(), "FQN cannot be empty");
let result = index.get(fqn);
// Assert negative space
if let Some(loc) = &result {
assert!(loc.uri.scheme() == "file", "Only file URIs supported");
}
result
}
ifs up, fors down// BAD: Recursion
fn traverse(node: &Node) {
process(node);
for child in node.children() {
traverse(child); // Recursive
}
}
// GOOD: Explicit stack
fn traverse(root: &Node) {
let mut stack = vec![root];
while let Some(node) = stack.pop() {
process(node);
stack.extend(node.children());
}
}
Centralize branching logic in parent functions. Keep leaf functions pure.
// BAD: Branching in leaf function
fn process_item(item: &Item, mode: Mode) {
if mode == Mode::Fast {
// fast path
} else {
// slow path
}
}
// GOOD: Branch in parent, pure leaves
fn process_items(items: &[Item], mode: Mode) {
match mode {
Mode::Fast => items.iter().for_each(process_fast),
Mode::Slow => items.iter().for_each(process_slow),
}
}
Every loop must have a clear termination condition. Every queue must have a capacity.
// BAD: Unbounded
while let Some(item) = queue.pop() {
process(item);
}
// GOOD: Bounded with safety limit
const MAX_ITERATIONS: usize = 10_000;
let mut iterations = 0;
while let Some(item) = queue.pop() {
iterations += 1;
assert!(iterations < MAX_ITERATIONS, "Infinite loop detected");
process(item);
}
fn find_definition_at_position(pos: Position) -> Option<Location>
let current_scope = get_scope();
// GOOD: Descending significance
let latency_ms_max = 100;
let timeout_seconds_default = 30;
let buffer_bytes_capacity = 1024;
// BAD
let max_latency_ms = 100;
let default_timeout_seconds = 30;
// GOOD
let definition_count = 0;
let reference_locations = vec![];
// BAD
let def_cnt = 0;
let ref_locs = vec![];
// GOOD
struct FqnResolver;
struct LspServer;
struct AstNode;
// BAD
struct FQNResolver;
struct LSPServer;
struct ASTNode;
// GOOD
// This function resolves the fully qualified name by traversing
// the scope chain from innermost to outermost.
// BAD
// resolve fqn using scope chain
// GOOD
// We use a two-phase approach because single-phase indexing
// cannot resolve forward references in Ruby's flexible syntax.
// BAD
// Index files in two phases.
/// Finds all references to the symbol at the given position.
///
/// # Invariants
/// - Position must be within document bounds
/// - Document must be indexed before calling
///
/// # Edge Cases
/// - Returns empty vec if position is in whitespace
/// - Includes declaration in results if `include_declaration` is true
fn find_references(pos: Position, include_declaration: bool) -> Vec<Location>
Never use debug_assert! - Use assert! and panic! instead.
Production correctness is more important than "graceful degradation" that hides bugs.
// ❌ NEVER DO THIS: Silent failure or wrong defaults
let fqn_id = self.get_fqn_id(fqn).unwrap_or_default();
// ❌ NEVER DO THIS: Debug-only checks
debug_assert!(fqn.is_valid()); // WRONG! Production won't catch this
// ✅ ALWAYS DO THIS: Crash loudly with clear message
let fqn_id = self.get_fqn_id(fqn).expect(
"INVARIANT VIOLATED: FQN not in index. \
This is a bug - index the file first."
);
// ✅ ALWAYS DO THIS: Assert in production too
assert!(fqn.is_valid(), "Invalid FQN: {}", fqn);
Why: Better to crash and fix the bug than silently produce wrong results that corrupt data or mislead users.
Every panic/assert must explain WHAT, WHY, and HOW:
// ✅ GOOD: Explains what, why, and how to fix
assert!(
matches!(fqn, Namespace(_, _)),
"INVARIANT VIOLATED: get_ancestor_chain called with {}.\n\
Only Namespace FQNs have ancestors (not Constants/Methods).\n\
Fix: Check the FQN type before calling this function.",
fqn
);
// ❌ BAD: Vague message
assert!(fqn.is_namespace(), "Invalid FQN");
"Almost all catastrophic system failures result from incorrect handling of non-fatal errors explicitly signaled in software."
// BAD: Silent failure
let _ = file.write_all(data);
// GOOD: Handle or propagate
file.write_all(data)?;
// GOOD: Log if truly optional
if let Err(e) = file.write_all(data) {
warn!("Failed to write cache: {}", e);
}
// Result: Operation can fail
fn read_file(path: &Path) -> Result<String, IoError>
// Option: Absence is normal/expected
fn find_symbol(name: &str) -> Option<Symbol>
If data is missing or invalid, PANIC - don't guess:
// ❌ BAD: Assuming/guessing
let kind = fqn.namespace_kind().unwrap_or(Instance); // Guessing!
// ✅ GOOD: Fail if wrong
let kind = match fqn {
Namespace(_, k) => k,
All|Variants => panic!("Expected Namespace FQN, got: {}", fqn), // Never use wildcard for panic/unreachable
};
Allocate at startup when possible. Avoid dynamic allocation in hot paths.
// GOOD: Pre-allocated buffer
let mut buffer = Vec::with_capacity(EXPECTED_SIZE);
// BAD: Repeated allocations
for item in items {
let mut temp = Vec::new(); // Allocates each iteration
// ...
}
// GOOD
let count: u32 = 0;
let offset: usize = 0;
// BAD: Ambiguous sizing
let count = 0; // What type?
Use Ustr for frequently compared or stored strings.
use ustr::Ustr;
// GOOD: Interned string
let name: Ustr = "MyClass".into();
// Compare with pointer equality
if name == other_name { ... }
main or primary entry point first// GOOD: Alphabetized imports
use crate::analyzer;
use crate::indexer;
use crate::query;
// GOOD: Alphabetized match arms (when equivalent)
match node {
Node::Class(c) => ...,
Node::Constant(c) => ...,
Node::Method(m) => ...,
Node::Module(m) => ...,
}
Break long lines for readability:
// GOOD
let result = some_function(
first_argument,
second_argument,
third_argument,
);
// BAD
let result = some_function(first_argument, second_argument, third_argument, fourth_argument);
debug_assert! - Use assert! instead (CRITICAL).unwrap_or_default() or silent failures (CRITICAL)