stemedb/crates/stemedb-sim/src/lib.rs
jordan 55349845d0 refactor: Split all files to enforce 500-line max
Break monolith source files into focused modules:
- stemedb-core/types.rs → types/ directory (assertion, source, gold_standard, etc.)
- stemedb-storage: audit_store, quota_store, trust_rank_store, vector_index, vote_store → module directories
- stemedb-ingest/worker.rs → worker/ with separate test modules
- stemedb-query: engine, materializer, query → module directories
- stemedb-lens: epoch_aware, skeptic → module directories
- stemedb-sim/lib.rs → agent, arenas/, helpers, runner, strategy, types
- stemedb-api/tests: integration_tests → http_basic, http_validation, http_epoch, http_pipeline
- stemedb-api/tests: e2e_flow_test → e2e_full_pipeline, e2e_lens_resolution
- stemedb-query/tests: e2e_pipeline → e2e_pipeline + e2e_decay

Also adds new features: gold standard verification, escalation handlers,
admin endpoints, concept hierarchy spec, arena roadmap, and Go SDK.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 01:13:45 -07:00

158 lines
6.1 KiB
Rust

//! StemeDB Simulation Library
//!
//! This module provides the core simulation logic for validating the StemeDB
//! "Spine" (Durability + Schema + Ingestion) and "Cortex" (Query + Lenses)
//! under agent-driven stress tests.
//!
//! # Design Philosophy
//!
//! Following "Philosophy of Software Design" principles:
//! - **Deep Module**: Simple `run_simulation()` interface hides all complexity
//! - **Define Errors Out of Existence**: Failures are collected, not panicked
//! - **Strategic Programming**: Built for testability and extension
//!
//! # Arena Phases
//!
//! - **Arena 0**: Spine validation (WAL + Ingestor + KV Store)
//! - **Arena 1**: Query path validation (QueryEngine + Lenses + Lifecycle + Audits)
//! - **Arena 2**: Voting & Consensus (VoteStore + VoteAwareConsensusLens)
//!
//! # Example
//!
//! ```ignore
//! use stemedb_sim::{run_simulation, SimulationConfig};
//!
//! let config = SimulationConfig::default();
//! let result = run_simulation(config).await?;
//!
//! assert_eq!(result.assertions_verified, result.assertions_written);
//! assert!(result.errors.is_empty());
//! ```
// Module declarations
mod agent;
mod arenas;
mod helpers;
mod runner;
pub mod strategy;
mod types;
// Public re-exports
pub use runner::run_simulation;
pub use strategy::{
AgentAction, AgentSpec, AgentStrategy, StrategyMetrics, StrategyType, WorldState,
};
pub use types::{
ErrorKind, SimulationConfig, SimulationError, SimulationResult, SimulationSetupError,
};
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_simulation_default_config_succeeds() {
let config = SimulationConfig::default();
let result = run_simulation(config).await.expect("Simulation should not fail setup");
assert!(result.is_success(), "Simulation should succeed: {:?}", result.errors);
// Arena 0: tick_count assertions (strategy-dependent, some agents may skip)
// Arena 2: 2 (vote consensus) + 2 (troll resistance)
// Arena 3: 1 (MV integration) + 1 (fast-path) + 10 (freshness)
assert!(result.assertions_written >= 16, "Should have arena test assertions + base");
// Arena 2 votes: 3 (vote consensus) + 3 (troll resistance)
assert!(result.votes_written >= 6);
assert!(result.recency_test_passed, "Recency test should pass");
assert!(result.lifecycle_test_passed, "Lifecycle test should pass");
assert!(result.audit_test_passed, "Audit test should pass");
assert!(result.vote_consensus_test_passed, "Vote consensus test should pass");
assert!(result.troll_resistance_test_passed, "Troll resistance test should pass");
assert!(result.mv_integration_test_passed, "MV integration test should pass");
assert!(result.fast_path_test_passed, "Fast-path test should pass");
assert!(result.mv_freshness_test_passed, "MV freshness test should pass");
}
#[tokio::test]
async fn test_simulation_custom_config() {
let config = SimulationConfig {
agents: vec![
AgentSpec { count: 2, strategy: StrategyType::Scientist },
AgentSpec { count: 2, strategy: StrategyType::Troll },
AgentSpec { count: 1, strategy: StrategyType::Believer },
],
tick_count: 20,
ingestion_wait_ms: 600,
};
let result = run_simulation(config).await.expect("Simulation should not fail setup");
assert!(result.is_success());
// Strategy-driven: agents may assert, vote, query, or skip per tick
assert!(result.assertions_written >= 16, "Should have arena test assertions + base");
assert!(result.votes_written >= 6);
assert_eq!(result.agent_count, 5);
assert_eq!(result.tick_count, 20);
}
#[tokio::test]
async fn test_simulation_result_summary() {
let success = SimulationResult {
assertions_written: 10,
assertions_verified: 10,
queries_executed: 12,
votes_written: 6,
recency_test_passed: true,
lifecycle_test_passed: true,
audit_test_passed: true,
vote_consensus_test_passed: true,
troll_resistance_test_passed: true,
mv_integration_test_passed: true,
fast_path_test_passed: true,
mv_freshness_test_passed: true,
persona_test_passed: true,
strategy_metrics: vec![],
views_materialized: 3,
errors: vec![],
agent_count: 3,
tick_count: 10,
};
assert!(success.summary().contains(""));
assert!(success.summary().contains("recency=✓"));
assert!(success.summary().contains("lifecycle=✓"));
assert!(success.summary().contains("audit=✓"));
assert!(success.summary().contains("vote_consensus=✓"));
assert!(success.summary().contains("troll_resist=✓"));
assert!(success.summary().contains("mv_integ=✓"));
assert!(success.summary().contains("fast_path=✓"));
assert!(success.summary().contains("mv_fresh=✓"));
let failure = SimulationResult {
assertions_written: 10,
assertions_verified: 8,
queries_executed: 10,
votes_written: 6,
recency_test_passed: false,
lifecycle_test_passed: true,
audit_test_passed: true,
vote_consensus_test_passed: true,
troll_resistance_test_passed: false,
mv_integration_test_passed: true,
fast_path_test_passed: false,
mv_freshness_test_passed: true,
persona_test_passed: true,
strategy_metrics: vec![],
views_materialized: 2,
errors: vec![SimulationError {
tick: 5,
kind: ErrorKind::VerificationFailure,
message: "Test error".to_string(),
}],
agent_count: 3,
tick_count: 10,
};
assert!(failure.summary().contains(""));
assert!(failure.summary().contains("recency=✗"));
assert!(failure.summary().contains("fast_path=✗"));
assert!(failure.summary().contains("troll_resist=✗"));
}
}