# Contributing to SymClaw Thank you for your interest in SymClaw! This guide will help you get started. ## Development Environment ### Nix (Recommended) ```bash git clone https://github.com/symclaw/symclaw.git cd symclaw nix develop # Drops you into a shell with Rust, wasm-pack, and all tools cargo test # Verify everything works ``` ### Manual Setup Requirements: - Rust 1.93.0+ (edition 2024) - wasm-pack (for WASM builds) - cargo-nextest (recommended for faster test runs) ```bash git clone https://github.com/symclaw/symclaw.git cd symclaw rustup toolchain install stable cargo test ``` ## Code Style - **Format**: `cargo fmt` — all code must pass `cargo fmt --check` - **Lint**: `cargo clippy` — zero warnings policy (pedantic + nursery enabled) - **No unsafe**: `unsafe` code is denied workspace-wide - **File limit**: Keep files under 1,250 lines. If a module grows past this, split it. - **Documentation**: All public items should have doc comments (`missing_docs` is warned) - **Error handling**: Use `thiserror` for library errors, `anyhow` for binary crates. No `.unwrap()` or `.expect()` (clippy-denied). ## Testing All PRs must pass the full test suite: ```bash # Run all tests cargo test --workspace # Run property-based tests (proptest) cargo test --workspace -- --include-ignored proptest # Run with nextest for parallel execution cargo nextest run --workspace ``` ### Test Requirements - **Unit tests**: Every public function needs at least one test - **Property tests**: Mathematical operations must have proptest coverage verifying algebraic identities (e.g., `simplify(simplify(x)) == simplify(x)`, `d/dx(integral(f, x)) == f`) - **Edge cases**: Test with zero, negative numbers, large coefficients, deeply nested expressions - **No flaky tests**: Tests must be deterministic. If randomized, use a fixed seed. Current test count: **426 tests** — PRs should not reduce this number. ## Pull Request Process 1. **Fork** the repository and create a branch from `main` 2. **Branch naming**: `feat/description`, `fix/description`, or `refactor/description` 3. **Make your changes** with tests 4. **Run the full check suite**: ```bash cargo fmt --check cargo clippy --workspace -- -D warnings cargo test --workspace ``` 5. **Open a PR** with a clear description of what and why 6. **CI must pass** — GitHub Actions runs tests on Linux, macOS, Windows, and WASM 7. **One approval** required from a maintainer ### Commit Messages Follow [Conventional Commits](https://www.conventionalcommits.org/): ``` feat(simplify): add trig identity sin²+cos²=1 fix(parser): handle implicit multiplication with parentheses docs: update API reference for taylor function test(integrate): add proptest for by-parts rule ``` ## Adding Rewrite Rules Rewrite rules are the heart of SymClaw's simplification engine. Adding new rules requires extra rigor: 1. **Correctness proof sketch**: In your PR description, provide a brief mathematical proof or reference that the rewrite is always valid 2. **Proptest coverage**: Add a property test that generates random expressions and verifies the rule preserves equality (via numeric evaluation) 3. **Benchmark**: Run `cargo bench` before and after. Rules that cause >5% regression in saturation time need justification 4. **E-graph tests**: Add a test in `egraph/` showing the rule fires and produces the expected extraction Example PR description for a new rule: ``` ## New rule: `ln(a*b) → ln(a) + ln(b)` (for a > 0, b > 0) **Proof**: Direct consequence of logarithm properties. Restriction to positive reals avoids complex branch issues. **Proptest**: Generates random positive a, b ∈ (0.01, 1000), verifies |ln(a*b) - (ln(a) + ln(b))| < 1e-10. **Benchmark**: No measurable change in saturation time (30 rules → 31). ``` ## Good First Issues Looking for a place to start? These are great entry points: - **Add missing trig identities** — e.g., double-angle formulas as rewrite rules - **Improve LaTeX rendering** — Better spacing for specific expression patterns - **CLI quality-of-life** — Tab completion for function names - **More integration patterns** — `∫ sec(x) dx`, `∫ csc(x) dx` - **WASM examples** — A simple web page demonstrating the WASM API - **Documentation** — Examples, tutorials, fixing typos - **Error messages** — Make parser errors more user-friendly with span information Check the [issue tracker](https://github.com/symclaw/symclaw/issues?q=label%3A%22good+first+issue%22) for labeled issues. ## Architecture Overview for New Contributors ``` symclaw-core (the engine — start here) ├── ast.rs # Expression tree: Arc with Symbol interning ├── parser.rs # nom-based parser: string → Arc ├── simplify.rs # Multi-pass simplification pipeline ├── egraph.rs # E-graph equality saturation (egg crate) ├── differentiate.rs# Symbolic differentiation ├── integrate.rs # Symbolic integration ├── solve.rs # Equation solver ├── series.rs # Taylor/Maclaurin expansion ├── eval.rs # Numeric evaluation (f64) ├── latex.rs # LaTeX rendering └── interner.rs # String interning for symbols ``` **Key design decisions:** - Expressions are `Arc` — immutable, cheaply cloneable, shared subtrees - Symbols are interned integers, not strings — fast comparison - Simplification runs before other operations — canonical form matters - E-graph is opt-in (used for deep simplification, not every operation) See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full deep dive. ## Code of Conduct This project follows the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct). Be kind, be constructive, be welcoming. ## Questions? - Open a [Discussion](https://github.com/symclaw/symclaw/discussions) on GitHub - Join our [Discord](https://discord.gg/symclaw) - Email: omar@symclaw.dev Thank you for helping make symbolic computing accessible to everyone! 🦀