Thank you for your interest in contributing to Primordium! This document provides guidelines and instructions for contributing to the project.
- Code of Conduct
- Getting Started
- Development Setup
- Contributing Guidelines
- Commit Message Convention
- Testing
- Documentation
- Pull Request Process
This project adheres to a code of conduct that expects all participants to:
- Be respectful and inclusive
- Welcome newcomers and help them learn
- Focus on constructive feedback
- Accept responsibility and apologize when mistakes happen
- Rust (latest stable version)
- Git
- Node.js (for WebAssembly development)
- wasm-pack (for WASM builds)
# Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/primordium.git
cd primordium
# Add upstream remote
git remote add upstream https://github.com/pplmx/primordium.git# Build the native TUI version
cargo build --release
# Run the simulation
cargo run --release
# Build for WebAssembly
cd www && wasm-pack build --target web# Run all tests
cargo test
# Run tests with output
cargo test -- --nocapture
# Run a specific test
cargo test test_name
# Run integration tests only
cargo test --test '*'# Format code
cargo fmt
# Run Clippy lints
cargo clippy -- -D warnings
# Check for security vulnerabilities
cargo auditWe welcome contributions in the following areas:
- Bug fixes: Fix issues reported in the codebase
- Feature implementations: Work on roadmap items (see ROADMAP.md)
- Documentation: Improve README, wiki, or inline comments
- Tests: Add missing test coverage
- Performance optimizations: Improve simulation performance
- Refactoring: Improve code structure and maintainability
- Follow Rust naming conventions
- Use descriptive variable names
- Keep functions focused and small
- Add comments explaining "why", not "what"
- Avoid
unwrap()andexpect()in production code - Use
?operator for error propagation
// ❌ Bad - can panic
let data = fs::read_to_string("config.toml").unwrap();
// ✅ Good - graceful error handling
let data = fs::read_to_string("config.toml")
.map_err(|e| {
tracing::error!("Failed to read config: {}", e);
e
})?;The project follows a layered architecture:
src/
├── model/ # Core simulation engine (no IO)
│ ├── state/ # Data structures
│ ├── systems/ # Logic/behavior
│ └── infra/ # External protocols
├── app/ # Application lifecycle
├── ui/ # Rendering
└── client/ # WASM client
- Model layer must be pure logic (no disk/network IO)
- Systems should be stateless functions
- State should only contain data (no methods that mutate)
We follow the Conventional Commits specification:
<type>(<scope>): <subject>
<body>
<footer>
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style (formatting, semicolons, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or fixing testschore: Build process or auxiliary tool changes
core: Core simulation enginebrain: Neural network logicui: User interfacenet: Networking/P2Pdocs: Documentationtest: Tests
feat(brain): add support for dynamic topology mutations
fix(net): handle websocket disconnect gracefully
docs(readme): update installation instructions
refactor(model): split World into smaller systems- All new features must include tests
- Bug fixes must include regression tests
- Maintain or improve code coverage
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_feature_behavior() {
// Arrange
let input = create_test_data();
// Act
let result = process(&input);
// Assert
assert_eq!(result.expected_value, actual_value);
}
#[test]
fn test_edge_case() {
// Test boundary conditions
}
}Integration tests are located in the tests/ directory:
tests/
├── lifecycle.rs # Life cycle tests
├── ecology.rs # Ecosystem tests
├── social_dynamics.rs # Social behavior tests
├── migration_network.rs # P2P networking tests
└── ...- All public APIs must have doc comments
- Use examples in documentation
- Explain the "why" behind complex logic
/// Calculates the social rank of an entity based on multiple factors.
///
/// The rank is computed as a weighted sum:
/// - Energy: 30%
/// - Age: 30%
/// - Offspring count: 10%
/// - Reputation: 30%
///
/// # Arguments
///
/// * `entity` - The entity to evaluate
/// * `context` - Additional contextual information
///
/// # Returns
///
/// A value between 0.0 and 1.0 representing the entity's social rank
///
/// # Examples
///
/// ```
/// let rank = calculate_social_rank(&entity, &context);
/// assert!(rank >= 0.0 && rank <= 1.0);
/// ```
pub fn calculate_social_rank(entity: &Entity, context: &Context) -> f32 {
// Implementation
}When adding features, update:
- CHANGELOG.md: Add entry under appropriate phase
- README.md: If user-facing feature
- Wiki docs (
docs/wiki/): If technical feature - AGENTS.md: If architecture changes
-
Sync with upstream:
git fetch upstream git rebase upstream/main
-
Run quality checks:
cargo fmt --check cargo clippy -- -D warnings cargo test -
Update documentation as needed
-
Write clear commit messages following our convention
-
Push to your fork:
git push origin feature/my-feature
-
Create Pull Request on GitHub
-
Fill out the PR template:
- Describe what changed and why
- Reference related issues
- Include screenshots for UI changes
- All PRs require at least one review
- Address review feedback promptly
- Keep PRs focused and reasonably sized
- Be open to feedback and discussion
- Delete your feature branch
- Update your local main branch
- Continue with a new branch for next contribution
If you have questions or need help:
- Check existing documentation
- Review ARCHITECTURE.md
- Open an issue for discussion
By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to Primordium! 🧬✨