stemedb/.claude/guides/coding-guidelines.md
jml 9bfa626203 docs: reorganize documentation structure for clarity
Major documentation restructure to improve discoverability and reduce duplication.

## Changes

**Deleted (Archived/Consolidated)**:
- Removed duplicate getting started guides
- Archived outdated planning documents
- Consolidated corpus and configuration docs
- Removed obsolete vision/spec files (superseded by vision.md)
- Cleaned up scrapyard and old PDFs

**New Structure**:
- docs/about/ - Project overview and introduction
- docs/guides/ - User guides (moved from root)
- docs/specs/ - Technical specifications
- docs/sdk/ - SDK documentation (Go)
- docs/references/ - API references
- docs/archive/ - Archived historical docs
- applications/aphoria/docs/advanced/ - Advanced topics
- applications/aphoria/docs/reference/ - CLI reference
- applications/aphoria/docs/archive/ - Archived aphoria docs

**Updated**:
- README.md - New root README with clear navigation
- CONTRIBUTING.md - Contribution guidelines
- CLAUDE.md - Updated paths to new structure
- roadmap.md - Added recent completions

## Files Changed
- 57 files changed
- 1,977 insertions(+)
- 961 deletions(-)

**Net change**: +1,016 lines (added CONTRIBUTING.md, README.md, reorganized content)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-11 07:33:40 +00:00

3.5 KiB

Rust Coding Guidelines

Core Stack

Component Required Forbidden
Error handling thiserror (lib), anyhow (bin) .unwrap(), .expect(), panic!
Serialization rkyv (zero-copy) serde_json for hot paths
Hashing blake3 sha256, md5
KV Store sled (MVP), trait-abstracted Direct rocksdb coupling
Async tokio (if needed) async-std
Logging tracing log, println!
Testing proptest, rstest Mocking core types

Error Handling

// Library errors: use thiserror
#[derive(Debug, thiserror::Error)]
pub enum StemeError {
    #[error("assertion not found: {0}")]
    NotFound(Hash),

    #[error("invalid signature for agent {agent}")]
    InvalidSignature { agent: AgentId },

    #[error("storage error: {0}")]
    Storage(#[from] sled::Error),
}

// Always add context
fn load_assertion(hash: &Hash) -> Result<Assertion, StemeError> {
    let bytes = self.store
        .get(hash)
        .context("failed to read from store")?
        .ok_or(StemeError::NotFound(*hash))?;
    // ...
}

Type Safety

Use newtypes for domain IDs:

// Good: Strong types
pub struct EntityId(pub String);
pub struct RelationId(pub String);
pub struct Hash(pub [u8; 32]);
pub struct AgentId(pub [u8; 32]);

// Bad: Stringly-typed
fn query(subject: String, predicate: String) -> ...

Formatting

  • Use underscores in numbers: 1_000_000 not 1000000
  • Use inline interpolation: println!("{hash:?}") not println!("{:?}", hash)
  • Max line length: 100 characters
  • Run cargo fmt before commit

Testing

#[cfg(test)]
mod tests {
    use super::*;
    use proptest::prelude::*;

    // Property test for critical invariants
    proptest! {
        #[test]
        fn assertion_round_trips(bytes in prop::collection::vec(any::<u8>(), 0..1000)) {
            let assertion = /* create from bytes */;
            let serialized = rkyv::to_bytes(&assertion)?;
            let deserialized = rkyv::from_bytes(&serialized)?;
            assert_eq!(assertion, deserialized);
        }
    }

    // Descriptive test names
    #[test]
    fn test_lens_consensus_returns_highest_vote_count() {
        // Arrange
        let assertions = vec![/* ... */];

        // Act
        let result = ConsensusLens.resolve(&assertions, &ctx);

        // Assert
        assert_eq!(result.value, expected);
    }
}

Module Structure

crates/stemedb-core/
  src/
    lib.rs           # Public API, re-exports
    assertion.rs     # Assertion struct
    types.rs         # EntityId, RelationId, Hash, etc.
    store.rs         # Storage trait
    error.rs         # StemeError
  tests/
    integration.rs   # Cross-module tests

Documentation

/// Resolves conflicting assertions using weighted voting.
///
/// # Arguments
/// * `candidates` - All assertions matching the query
/// * `context` - Query context including agent reputations
///
/// # Returns
/// The assertion with highest weighted support, or None if empty.
///
/// # Example
/// ```
/// let lens = ConsensusLens::default();
/// let result = lens.resolve(&assertions, &ctx);
/// ```
pub fn resolve(&self, candidates: &[Assertion], context: &QueryContext) -> Option<Assertion> {
    // ...
}

Clippy

Must pass with zero warnings:

cargo clippy --workspace -- -D warnings

Common fixes:

  • needless_return: Remove explicit return when implicit works
  • redundant_clone: Check if clone is actually needed
  • missing_docs: Add doc comments to public items