Contributing
π€ Guidelines for contributing to PiSovereign
Thank you for your interest in contributing to PiSovereign! This guide will help you get started.
Table of Contents
Code of Conduct
This project adheres to a Code of Conduct. By participating, you are expected to:
- Be respectful and inclusive
- Accept constructive criticism gracefully
- Focus on whatβs best for the community
- Show empathy towards others
Development Setup
Prerequisites
| Requirement | Version | Notes |
|---|---|---|
| Rust | 1.93.0+ | Edition 2024 |
| Just | Latest | Command runner |
| SQLite | 3.x | Development database |
| FFmpeg | 5.x+ | Audio processing |
Environment Setup
- Clone the repository
git clone https://github.com/twohreichel/PiSovereign.git
cd PiSovereign
- Install Rust toolchain
# Install rustup if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install required components
rustup component add rustfmt clippy
# Install nightly for docs (optional)
rustup toolchain install nightly
- Install Just
# macOS
brew install just
# Linux
cargo install just
- Install development dependencies
# macOS
brew install sqlite ffmpeg
# Ubuntu/Debian
sudo apt install libsqlite3-dev ffmpeg pkg-config libssl-dev
- Verify setup
# Run quality checks
just quality
# Build the project
just build
Running Tests
# Run all tests
just test
# Run tests with output
just test-verbose
# Run specific crate tests
cargo test -p domain
cargo test -p application
# Run integration tests
cargo test --test '*' -- --ignored
# Generate coverage report
just coverage
Code Style
Rust Formatting
We use rustfmt with custom configuration:
# Format all code
just fmt
# Check formatting (CI will fail if not formatted)
just fmt-check
Configuration in rustfmt.toml:
edition = "2024"
max_width = 100
use_small_heuristics = "Default"
imports_granularity = "Crate"
group_imports = "StdExternalCrate"
Clippy Lints
We enforce strict Clippy lints:
# Run clippy
just lint
# Auto-fix issues
just lint-fix
Key lint categories enabled:
clippy::pedantic- Strict lintsclippy::nursery- Experimental but useful lintsclippy::cargo- Cargo.toml best practices
Commit Messages
We follow Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
Types:
| Type | Description |
|---|---|
feat | New feature |
fix | Bug fix |
docs | Documentation only |
style | Code style (formatting, no logic change) |
refactor | Code change that neither fixes nor adds |
perf | Performance improvement |
test | Adding or updating tests |
chore | Maintenance tasks |
Examples:
feat(api): add streaming chat endpoint
Implements SSE-based streaming for /v1/chat/stream endpoint.
Supports token-by-token response streaming for better UX.
Closes #123
fix(inference): handle timeout gracefully
Previously, inference timeouts caused a panic. Now returns
a proper error response with retry information.
Documentation
All public APIs must be documented:
/// Processes a user message and returns an AI response.
///
/// This method handles the full conversation flow including:
/// - Loading conversation context
/// - Calling the inference engine
/// - Persisting the response
///
/// # Arguments
///
/// * `conversation_id` - Optional ID to continue existing conversation
/// * `message` - The user's message content
///
/// # Returns
///
/// Returns the AI's response or an error if processing fails.
///
/// # Errors
///
/// - `ServiceError::Inference` - If the inference engine is unavailable
/// - `ServiceError::Database` - If conversation persistence fails
///
/// # Examples
///
/// ```rust,ignore
/// let response = service.send_message(
/// Some(conversation_id),
/// "What's the weather?".to_string(),
/// ).await?;
/// ```
pub async fn send_message(
&self,
conversation_id: Option<ConversationId>,
message: String,
) -> Result<Message, ServiceError> {
// ...
}
Pull Request Process
Before You Start
-
Check existing issues/PRs
- Look for related issues or PRs
- Comment on the issue you want to work on
-
Create an issue first (for features)
- Describe the feature
- Discuss approach before implementing
-
Fork and branch
git checkout -b feat/my-feature # or git checkout -b fix/issue-123
Creating a PR
-
Ensure quality checks pass
just pre-commit -
Write/update tests
- Add tests for new functionality
- Ensure existing tests still pass
-
Update documentation
- Update relevant docs in
docs/ - Add doc comments to new public APIs
- Update relevant docs in
-
Push and create PR
git push origin feat/my-feature -
Fill out PR template
- Description of changes
- Related issues
- Testing performed
- Breaking changes (if any)
PR Template
## Description
Brief description of what this PR does.
## Related Issues
Fixes #123
Related to #456
## Type of Change
- [ ] Bug fix (non-breaking)
- [ ] New feature (non-breaking)
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manually tested on Raspberry Pi
## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No new warnings
Review Process
-
Automated checks must pass:
- Format check (
rustfmt) - Lint check (
clippy) - Tests (all platforms)
- Coverage (no significant decrease)
- Security scan (
cargo-deny)
- Format check (
-
Human review:
- At least one maintainer approval required
- Address all review comments
-
Merge:
- Squash and merge for clean history
- Delete branch after merge
Development Workflow
Common Tasks
# Full quality check (run before pushing)
just quality
# Quick pre-commit check
just pre-commit
# Run the server locally
just run
# Run CLI commands
just cli status
just cli chat "Hello"
# Generate and view documentation
just docs
# Clean build artifacts
just clean
Project Structure
PiSovereign/
βββ crates/ # Rust crates
β βββ domain/ # Core business logic
β βββ application/ # Use cases, services
β βββ infrastructure/ # External adapters
β βββ ai_core/ # Inference engine
β βββ ai_speech/ # Speech processing
β βββ integration_*/ # Service integrations
β βββ presentation_*/ # HTTP API, CLI
βββ docs/ # mdBook documentation
βββ grafana/ # Monitoring configuration
βββ migrations/ # Database migrations
βββ .github/ # CI/CD workflows
Adding a New Feature
-
Domain layer (if new entities/values needed)
# Edit crates/domain/src/entities/mod.rs # Add new entity module -
Application layer (service logic)
# Add port trait in crates/application/src/ports/ # Add service in crates/application/src/services/ -
Infrastructure layer (adapters)
# Implement port in crates/infrastructure/src/adapters/ -
Presentation layer (API endpoints)
# Add handler in crates/presentation_http/src/handlers/ # Add route in crates/presentation_http/src/router.rs -
Tests
# Unit tests alongside code # Integration tests in crates/*/tests/
Database Migrations
# Create new migration
cat > migrations/V007__my_migration.sql << 'EOF'
-- Description of migration
CREATE TABLE my_table (
id TEXT PRIMARY KEY,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
EOF
# Migrations run automatically on startup (if enabled)
# Or manually:
pisovereign-cli migrate
Getting Help
- Questions: Use GitHub Discussions
- Bugs: Open an Issue
- Security: Report via GitHub Security Advisories
Thank you for contributing! π