312 lines
7.2 KiB
Markdown
312 lines
7.2 KiB
Markdown
|
|
# Code Standards
|
||
|
|
|
||
|
|
BotServer follows Rust best practices with a unique approach: **all code is fully generated by LLMs** following specific prompts and patterns.
|
||
|
|
|
||
|
|
## LLM-Generated Code Policy
|
||
|
|
|
||
|
|
### Core Principle
|
||
|
|
|
||
|
|
**All source code in BotServer is generated by Large Language Models (LLMs)**. This ensures consistency, reduces human error, and leverages AI capabilities for optimal code generation.
|
||
|
|
|
||
|
|
### Important Guidelines
|
||
|
|
|
||
|
|
1. **Comments are discouraged** - Code should be self-documenting through clear naming and structure
|
||
|
|
2. **Comments may be deleted during optimization** - Do not rely on comments for critical information
|
||
|
|
3. **Documentation should be external** - Use README files and documentation chapters, not inline comments
|
||
|
|
4. **Your comments are dangerous** - They can become outdated (desacoplado) and misleading
|
||
|
|
|
||
|
|
### Why No Comments?
|
||
|
|
|
||
|
|
- LLM-generated code is consistently structured
|
||
|
|
- Function and variable names are descriptive
|
||
|
|
- External documentation is more maintainable
|
||
|
|
- Comments become stale and misleading over time
|
||
|
|
- Optimization passes may remove comments
|
||
|
|
|
||
|
|
## Development Workflow
|
||
|
|
|
||
|
|
Follow the LLM workflow defined in `/prompts/dev/platform/README.md`:
|
||
|
|
|
||
|
|
### LLM Strategy
|
||
|
|
|
||
|
|
1. **Sequential Development**: One requirement at a time with sequential commits
|
||
|
|
2. **Fallback Strategy**: After 3 attempts or 10 minutes, try different LLMs in sequence
|
||
|
|
3. **Error Handling**: Stop on unresolved errors and consult alternative LLMs
|
||
|
|
4. **Warning Removal**: Handle as last task before committing
|
||
|
|
5. **Final Validation**: Use `cargo check` with appropriate LLM
|
||
|
|
|
||
|
|
### Code Generation Rules
|
||
|
|
|
||
|
|
From `/prompts/dev/platform/botserver.md`:
|
||
|
|
- Sessions must always be retrieved by id when session_id is present
|
||
|
|
- Never suggest installing software - bootstrap handles everything
|
||
|
|
- Configuration stored in `.gbot/config` and `bot_configuration` table
|
||
|
|
|
||
|
|
## Rust Style Guide
|
||
|
|
|
||
|
|
### Formatting
|
||
|
|
|
||
|
|
Use `rustfmt` for automatic formatting:
|
||
|
|
```bash
|
||
|
|
# Format all code
|
||
|
|
cargo fmt
|
||
|
|
|
||
|
|
# Check formatting without changes
|
||
|
|
cargo fmt -- --check
|
||
|
|
```
|
||
|
|
|
||
|
|
Configuration in `.rustfmt.toml`:
|
||
|
|
```toml
|
||
|
|
edition = "2021"
|
||
|
|
max_width = 100
|
||
|
|
use_small_heuristics = "Max"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Linting
|
||
|
|
|
||
|
|
Use `clippy` for code quality:
|
||
|
|
```bash
|
||
|
|
# Run clippy
|
||
|
|
cargo clippy -- -D warnings
|
||
|
|
|
||
|
|
# Fix clippy suggestions
|
||
|
|
cargo clippy --fix
|
||
|
|
```
|
||
|
|
|
||
|
|
## Naming Conventions
|
||
|
|
|
||
|
|
### General Rules
|
||
|
|
|
||
|
|
- **snake_case**: Functions, variables, modules
|
||
|
|
- **PascalCase**: Types, traits, enums
|
||
|
|
- **SCREAMING_SNAKE_CASE**: Constants
|
||
|
|
- **'lifetime**: Lifetime parameters
|
||
|
|
|
||
|
|
### Self-Documenting Names
|
||
|
|
|
||
|
|
Instead of comments, use descriptive names:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
// BAD: Needs comment
|
||
|
|
fn proc(d: &str) -> Result<String> {
|
||
|
|
// Process user data
|
||
|
|
// ...
|
||
|
|
}
|
||
|
|
|
||
|
|
// GOOD: Self-documenting
|
||
|
|
fn process_user_registration_data(registration_form: &str) -> Result<String> {
|
||
|
|
// No comment needed
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Code Organization
|
||
|
|
|
||
|
|
### Module Structure
|
||
|
|
|
||
|
|
```rust
|
||
|
|
// mod.rs or lib.rs
|
||
|
|
pub mod user;
|
||
|
|
pub mod session;
|
||
|
|
pub mod auth;
|
||
|
|
|
||
|
|
// Re-exports
|
||
|
|
pub use user::User;
|
||
|
|
pub use session::Session;
|
||
|
|
```
|
||
|
|
|
||
|
|
### Import Ordering
|
||
|
|
|
||
|
|
```rust
|
||
|
|
// 1. Standard library
|
||
|
|
use std::collections::HashMap;
|
||
|
|
use std::sync::Arc;
|
||
|
|
|
||
|
|
// 2. External crates
|
||
|
|
use tokio::sync::Mutex;
|
||
|
|
use uuid::Uuid;
|
||
|
|
|
||
|
|
// 3. Local crates
|
||
|
|
use crate::config::Config;
|
||
|
|
use crate::models::User;
|
||
|
|
|
||
|
|
// 4. Super/self
|
||
|
|
use super::utils;
|
||
|
|
use self::helper::*;
|
||
|
|
```
|
||
|
|
|
||
|
|
## Documentation Strategy
|
||
|
|
|
||
|
|
### External Documentation Only
|
||
|
|
|
||
|
|
```rust
|
||
|
|
// DON'T: Inline documentation comments
|
||
|
|
/// This function creates a user session
|
||
|
|
/// It takes a user_id and bot_id
|
||
|
|
/// Returns a Result with Session or Error
|
||
|
|
fn create_session(user_id: Uuid, bot_id: Uuid) -> Result<Session> {
|
||
|
|
// Implementation
|
||
|
|
}
|
||
|
|
|
||
|
|
// DO: Self-documenting code + external docs
|
||
|
|
fn create_user_session_for_bot(user_id: Uuid, bot_id: Uuid) -> Result<Session> {
|
||
|
|
// Implementation
|
||
|
|
}
|
||
|
|
// Document in chapter-10/api-reference.md instead
|
||
|
|
```
|
||
|
|
|
||
|
|
### Where to Document
|
||
|
|
|
||
|
|
1. **README.md** files for module overview
|
||
|
|
2. **Documentation chapters** for detailed explanations
|
||
|
|
3. **API references** in separate documentation files
|
||
|
|
4. **Architecture diagrams** in documentation folders
|
||
|
|
5. **Prompt files** in `/prompts/dev/` for generation patterns
|
||
|
|
|
||
|
|
## Error Handling
|
||
|
|
|
||
|
|
### Use Result Types
|
||
|
|
|
||
|
|
```rust
|
||
|
|
fn read_configuration_file(path: &str) -> Result<String, std::io::Error> {
|
||
|
|
std::fs::read_to_string(path)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Custom Error Types
|
||
|
|
|
||
|
|
```rust
|
||
|
|
use thiserror::Error;
|
||
|
|
|
||
|
|
#[derive(Error, Debug)]
|
||
|
|
pub enum BotServerError {
|
||
|
|
#[error("Database connection failed: {0}")]
|
||
|
|
DatabaseConnection(#[from] diesel::result::Error),
|
||
|
|
|
||
|
|
#[error("Invalid configuration: {message}")]
|
||
|
|
InvalidConfiguration { message: String },
|
||
|
|
|
||
|
|
#[error("Network request failed")]
|
||
|
|
NetworkFailure(#[from] reqwest::Error),
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing Standards
|
||
|
|
|
||
|
|
### Test Naming
|
||
|
|
|
||
|
|
```rust
|
||
|
|
#[test]
|
||
|
|
fn user_creation_succeeds_with_valid_data() {
|
||
|
|
// Clear test name, no comments needed
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn user_creation_fails_with_invalid_email() {
|
||
|
|
// Self-documenting test name
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Test Organization
|
||
|
|
|
||
|
|
```rust
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
mod user_creation {
|
||
|
|
#[test]
|
||
|
|
fn with_valid_data() {}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn with_invalid_email() {}
|
||
|
|
}
|
||
|
|
|
||
|
|
mod user_authentication {
|
||
|
|
#[test]
|
||
|
|
fn with_correct_password() {}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn with_wrong_password() {}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Security Standards
|
||
|
|
|
||
|
|
### Never Hardcode Secrets
|
||
|
|
|
||
|
|
```rust
|
||
|
|
let api_key = std::env::var("API_KEY")?;
|
||
|
|
let database_url = std::env::var("DATABASE_URL")?;
|
||
|
|
```
|
||
|
|
|
||
|
|
### Validate Input
|
||
|
|
|
||
|
|
```rust
|
||
|
|
fn validate_and_sanitize_user_input(input: &str) -> Result<String> {
|
||
|
|
if input.len() > MAX_INPUT_LENGTH {
|
||
|
|
return Err(BotServerError::InputTooLong);
|
||
|
|
}
|
||
|
|
|
||
|
|
if !input.chars().all(char::is_alphanumeric) {
|
||
|
|
return Err(BotServerError::InvalidCharacters);
|
||
|
|
}
|
||
|
|
|
||
|
|
Ok(input.to_string())
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Performance Guidelines
|
||
|
|
|
||
|
|
### Use Iterators
|
||
|
|
|
||
|
|
```rust
|
||
|
|
let positive_doubled_sum: i32 = numbers
|
||
|
|
.iter()
|
||
|
|
.filter(|n| **n > 0)
|
||
|
|
.map(|n| n * 2)
|
||
|
|
.sum();
|
||
|
|
```
|
||
|
|
|
||
|
|
### Avoid Unnecessary Allocations
|
||
|
|
|
||
|
|
```rust
|
||
|
|
fn process_text_without_allocation(text: &str) -> String {
|
||
|
|
text.to_uppercase()
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## LLM Prompt References
|
||
|
|
|
||
|
|
Key prompts for code generation are stored in `/prompts/dev/`:
|
||
|
|
|
||
|
|
- **platform/botserver.md**: Core platform rules
|
||
|
|
- **platform/add-keyword.md**: Adding new BASIC keywords
|
||
|
|
- **platform/add-model.md**: Integrating new LLM models
|
||
|
|
- **platform/fix-errors.md**: Error resolution patterns
|
||
|
|
- **basic/doc-keyword.md**: BASIC keyword documentation
|
||
|
|
|
||
|
|
## Code Review Checklist
|
||
|
|
|
||
|
|
Before submitting LLM-generated code:
|
||
|
|
|
||
|
|
- [ ] Code compiles without warnings
|
||
|
|
- [ ] All tests pass
|
||
|
|
- [ ] Code is formatted with rustfmt
|
||
|
|
- [ ] Clippy passes without warnings
|
||
|
|
- [ ] NO inline comments (use external docs)
|
||
|
|
- [ ] Function/variable names are self-documenting
|
||
|
|
- [ ] No hardcoded secrets
|
||
|
|
- [ ] Error handling follows Result pattern
|
||
|
|
- [ ] Follows patterns from `/prompts/dev/`
|
||
|
|
|
||
|
|
## Summary
|
||
|
|
|
||
|
|
BotServer embraces AI-first development where:
|
||
|
|
1. **All code is LLM-generated** following consistent patterns
|
||
|
|
2. **Comments are forbidden** - code must be self-documenting
|
||
|
|
3. **Documentation lives externally** in dedicated files
|
||
|
|
4. **Prompts define patterns** in `/prompts/dev/`
|
||
|
|
5. **Optimization may delete anything** not in the actual code logic
|
||
|
|
|
||
|
|
This approach ensures consistency, maintainability, and leverages AI capabilities while avoiding the pitfalls of outdated comments and human inconsistencies.
|