Skip to content

Commit 2eebcfe

Browse files
authored
AI assist rules
1 parent 14f11d9 commit 2eebcfe

11 files changed

+1117
-0
lines changed

.cursor/mcp.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"mcpServers": {
3+
"filesystem": {
4+
"command": "npx",
5+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
6+
}
7+
}
8+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
description: Guidelines for AI Assistants
3+
globs: "**/*"
4+
alwaysApply: true
5+
---
6+
7+
# Guidelines for AI Assistants
8+
9+
This file contains standards for how AI assistants should interact with codebases and follow project guidelines.
10+
11+
## Core Principles
12+
13+
1. **Autonomy**: Take responsibility for following all project rules without requiring reminders.
14+
2. **Consistency**: Maintain consistency with the existing codebase and established patterns.
15+
3. **Proactivity**: Anticipate rule requirements before starting work on any task.
16+
4. **Accuracy**: Ensure adherence to all relevant guidelines in every implementation.
17+
18+
## Things to avoid
19+
20+
1. Making changes unrelated to the task at hand - if you see other things in a file that could be improved, suggest them to the user!
21+
2. Getting stuck for a long time without asking for help - if you're struggling, just ask.
22+
23+
## Self-Checking Process
24+
25+
When working on any project task:
26+
27+
1. **Discovery**:
28+
- Identify all relevant rule files for the current context
29+
- Scan directories like `.cursor/rules/` for applicable guidelines
30+
- Look for language-specific, style, and organizational conventions
31+
32+
2. **Preparation**:
33+
- Review all applicable guidelines before beginning work
34+
- Identify patterns in existing code that demonstrate rule application
35+
- Prioritize project-specific conventions over generic best practices
36+
37+
3. **Validation**:
38+
- Before submitting any changes, verify compliance with ALL project guidelines
39+
- Ensure consistency with surrounding code
40+
- Detect and correct any rule violations proactively
41+
42+
## Effective Rule Application
43+
44+
For any development task:
45+
46+
1. **Context Assessment**:
47+
- Determine which rules apply to the current task
48+
- Consider the specific file type, language, and component
49+
50+
2. **Implementation Guidance**:
51+
- Apply relevant rules throughout the implementation process
52+
- Use existing code patterns as guidance for ambiguous cases
53+
- Maintain the established style and conventions
54+
55+
3. **Quality Assurance**:
56+
- Verify rule compliance before finalizing work
57+
- Ensure consistency across similar components
58+
- Validate that all project-specific requirements are met
59+
60+
## Common Pitfalls to Avoid
61+
62+
- Requiring reminders about existing project guidelines
63+
- Implementing solutions that contradict established patterns
64+
- Applying inconsistent approaches across similar tasks
65+
- Overlooking project-specific conventions in favor of generic practices
66+
- Introducing deviations from standards without explicit justification
67+
68+
AI assistants should consistently enforce project guidelines without being prompted. Your role includes ensuring that all contributions adhere to the established rules of the project.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
description: Git convention
3+
globs:
4+
alwaysApply: true
5+
---
6+
# Git Commit Conventions
7+
8+
This project follows specific conventions for git commit messages.
9+
10+
## Commit Message Format
11+
12+
Commit messages should:
13+
14+
1. Be descriptive and concise
15+
2. Use sentence case (capitalize first word)
16+
3. Describe the change in an imperative, present-tense style
17+
4. Not use semantic prefixes (like "fix:", "feat:", "chore:")
18+
19+
## Examples
20+
21+
### Good commit messages:
22+
23+
```text
24+
Add feature flags to Real type tests that require `serde`
25+
Update performance documentation guidelines
26+
Fix PostgreSQL integration type reference issues
27+
Improve error handling in token validation
28+
```
29+
30+
### Avoid semantic prefixes:
31+
32+
```text
33+
// Don't use these formats
34+
fix: add feature flags to tests
35+
feat: implement new logging system
36+
chore: update dependencies
37+
docs: update README
38+
```
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
---
2+
description: Rust Coding Style
3+
globs: "**/*.rs"
4+
alwaysApply: false
5+
---
6+
# Rust Coding Style
7+
8+
## Project-Specific Patterns
9+
10+
- Use the 2024 edition of Rust
11+
- Prefer `derive_more` over manual trait implementations
12+
- Feature flags in this codebase use the `#[cfg(feature = "...")]` pattern
13+
- Invoke `cargo clippy` with `--all-features`, `--all-targets`, and `--no-deps` from the root
14+
- Use `cargo doc --no-deps --all-features` for checking documentation
15+
- Use `rustfmt` to format the code
16+
- Use `#[expect(lint, reason = "...")]` over `#[allow(lint)]`
17+
18+
## Type System
19+
20+
- Create strong types with newtype patterns for domain entities
21+
- Implement `hash_graph_types` traits for custom domain types
22+
- Consider visibility carefully (avoid unnecessary `pub`)
23+
24+
```rust
25+
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, derive_more::Display)]
26+
pub struct UserId(Uuid);
27+
```
28+
29+
## Async Patterns
30+
31+
- Use `impl Future<Output = T> + Send` in trait definitions:
32+
33+
```rust
34+
fn get_data(
35+
&self,
36+
id: String,
37+
) -> impl Future<Output = Result<Data, Report<DataError>>> + Send {
38+
async move {
39+
// Implementation
40+
}
41+
}
42+
```
43+
44+
## Function Arguments
45+
46+
- Functions should **never** take more than 7 arguments. If a function requires more than 7 arguments, encapsulate related parameters in a struct.
47+
- Functions that use data immutably should take a reference to the data, while functions that modify data should take a mutable reference. Never take ownership of data unless the function explicitly consumes it.
48+
- Make functions `const` whenever possible.
49+
- Prefer the following argument types when applicable, but only if this does not reduce performance:
50+
- `impl AsRef<str>` instead of `&str` or `&String`
51+
- `impl AsRef<Path>` instead of `&Path` or `&PathBuf`
52+
- `impl IntoIterator<Item = &T>` when only iterating over the data
53+
- `&[T]` instead of `&Vec<T>`
54+
- `&mut [T]` instead of `&mut Vec<T>` when the function doesn't need to resize the vector
55+
- `impl Into<Cow<T>>` instead of `Cow<T>`
56+
- `impl Into<Arc<T>>` instead of `Arc<T>`
57+
- `impl Into<Rc<T>>` instead of `Rc<T>`
58+
- `impl Into<Box<T>>` instead of `Box<T>`
59+
- Never use `impl Into<Option<_>>` as from reading the caller site, it's not visible that `None` could potentially be passed
60+
61+
## `From` and `Into`
62+
63+
- Generally prefer `From` implementations over `Into` implementations. The Rust compiler will automatically derive `Into` from `From`, but not vice versa.
64+
- When converting between types, prefer using the `from` method over `into` for clarity. The `from` method makes the target type explicit in the code, while `into` requires type inference.
65+
- For wrapper types like `Cow`, `Arc`, `Rc`, `Report`, and `Box`, prefer using explicit constructors (e.g., `Cow::from`, `Arc::new`) instead of `.into()`. This improves readability by clearly indicating the target type.
66+
67+
## Smart Pointers
68+
69+
- When cloning smart pointers such as `Arc` and `Rc`, **always** use `Arc::clone(&pointer)` and `Rc::clone(&pointer)` instead of `pointer.clone()`. This explicitly indicates you're cloning the reference, not the underlying data.
70+
71+
## Instrumentation
72+
73+
- Annotate functions that perform significant work with `#[tracing::instrument]`
74+
- Use `tracing` macros (e.g., `trace!`, `debug!`, `info!`, `warn!`, `error!`) instead of `println!` or `eprintln!` for logging
75+
76+
## Allocations
77+
78+
- Minimize allocations when possible. For example, reuse a `Vec` in a loop instead of creating a new one in each iteration.
79+
- Prefer borrowed data over owned data where appropriate.
80+
- Balance performance and readability—if an allocation makes code significantly more readable or maintainable, the trade-off may be worthwhile.
81+
82+
## Types
83+
84+
- Use newtypes when a value should carry specific semantics beyond its underlying type. This improves type safety and code clarity.
85+
86+
For example:
87+
88+
```rust
89+
struct UserId(u64); // instead of `type UserId = u64;` or `u64`
90+
```
91+
92+
## Naming Conventions
93+
94+
When suggesting names for variables, functions, or types:
95+
96+
- Do not prefix test-function names with `test_`, this would otherwise result in `test::test_<name>` names.
97+
- Provide a concise list of naming options with brief explanations of why each fits the context
98+
- Choose names of appropriate length—avoid names that are too long or too short
99+
- Avoid abbreviations unless they are widely recognized in the domain (e.g., `Http` or `Json` is acceptable, but `Ctx` instead of `Context` is not)
100+
- Do not suffix names with their types (e.g., use `users` instead of `usersList`)
101+
- Do not repeat the type name in variable names (e.g., use `user` instead of `userUser`)
102+
103+
## Crate Preferences
104+
105+
- Use `similar_asserts` for test assertions
106+
- Use `insta` for snapshot tests
107+
- Use `test_log` for better test output (`#[test_log::test]`)
108+
- Use `tracing` macros, not `log` macros
109+
- Prefer `tracing::instrument` for function instrumentation
110+
111+
## Import Style
112+
113+
- Don't use local imports within functions, or blocks
114+
- Avoid wildcard imports like `use super::*;`, or `use crate::module::*;`
115+
- Never use a prelude `use crate::prelude::*`
116+
- Prefer explicit imports to make dependencies clear and improve code readability
117+
- We prefer `core` over `alloc` over `std` for imports to minimize dependencies
118+
- Use `core` for functionality that doesn't require allocation
119+
- Use `alloc` when you need allocation but not OS-specific features
120+
- Only use `std` when necessary for OS interactions or when using `core`/`alloc` would be unnecessarily complex
121+
- Prefer qualified imports (`use foo::Bar; let x = Bar::new()`) over fully qualified paths (`let x = foo::Bar::new()`) for frequently used types
122+
- Use `pub use` re-exports in module roots to create a clean public API
123+
- Avoid importing items with the same name from different modules; use qualified imports
124+
- Import traits using `use module::Trait as _;` when you only need the trait's methods and not the trait name itself
125+
- This pattern brings trait methods into scope without name conflicts
126+
- Use this especially for extension traits or when implementing foreign traits on local types
127+
128+
```rust
129+
// Good - Importing a trait just for its methods:
130+
use std::io::Read as _;
131+
132+
// Example with trait methods:
133+
fn read_file(file: &mut File) -> Result<String, std::io::Error> {
134+
// Read methods available without importing the Read trait name
135+
let mut content = String::new();
136+
file.read_to_string(&mut content)?;
137+
Ok(content)
138+
}
139+
140+
// Bad - Directly importing trait when only methods are needed:
141+
use std::io::Read;
142+
143+
// Good - Importing trait for implementing it:
144+
use std::io::Write;
145+
impl Write for MyWriter { /* implementation */ }
146+
147+
// Bad - Wildcard import:
148+
mod tests {
149+
use super::*; // Wildcard import
150+
151+
#[test]
152+
fn test_something() {
153+
// Test implementation
154+
}
155+
}
156+
157+
// Good - Explicit imports:
158+
mod tests {
159+
use crate::MyStruct;
160+
use crate::my_function;
161+
162+
#[test]
163+
fn test_something() {
164+
// Test implementation
165+
}
166+
}
167+
168+
// Bad - Local import:
169+
fn process_data() {
170+
use std::collections::HashMap; // Local import
171+
let map = HashMap::new();
172+
// Implementation
173+
}
174+
175+
// Good - Module-level import:
176+
use std::collections::HashMap;
177+
178+
fn process_data() {
179+
let map = HashMap::new();
180+
// Implementation
181+
}
182+
183+
// Bad - Using std when core would suffice:
184+
use std::fmt::Display;
185+
186+
// Good - Using core for non-allocating functionality:
187+
use core::fmt::Display;
188+
189+
// Bad - Using std when alloc would suffice:
190+
use std::collections::BTreeSet;
191+
192+
// Good - Using alloc for allocation without full std dependency:
193+
use alloc::vec::Vec;
194+
195+
// Appropriate - Using std when needed:
196+
use std::fs::File; // OS-specific functionality requires std
197+
```
198+
199+
## Libraries and Components
200+
201+
- Abstract integrations with third-party systems behind traits to maintain clean separation of concerns
202+
203+
## Comments and Assertions
204+
205+
- Do not add comments after a line of code; place comments on separate lines above the code they describe
206+
- When using assertions, include descriptive messages using the optional description parameter rather than adding a comment
207+
- All `expect()` messages should follow the format "should ..." to clearly indicate the expected behavior
208+
209+
For example:
210+
211+
```rust
212+
// Bad:
213+
assert_eq!(result, expected); // This should match the expected value
214+
215+
// Good:
216+
assert_eq!(result, expected, "Values should match expected output");
217+
218+
// Bad:
219+
some_value.expect("The value is not None"); // This should never happen
220+
221+
// Good:
222+
some_value.expect("should contain a valid value");
223+
```

0 commit comments

Comments
 (0)