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>
145 lines
3.5 KiB
Markdown
145 lines
3.5 KiB
Markdown
# 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
|
|
|
|
```rust
|
|
// 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:
|
|
|
|
```rust
|
|
// 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
|
|
|
|
```rust
|
|
#[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
|
|
|
|
```rust
|
|
/// 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:
|
|
|
|
```bash
|
|
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
|