Testing
Use deterministic models and the production-request guard for safe tests.
TestModel
#![allow(unused)]
fn main() {
use std::sync::Arc;
use starweaver_agent::{AgentBuilder, TestModel};
async fn example() -> Result<(), starweaver_agent::AgentError> {
let test_model = Arc::new(TestModel::with_text("test response"));
let agent = AgentBuilder::new(test_model).build();
let result = agent.run("hello").await?;
assert_eq!(result.output, "test response");
Ok(())
}
}
Scoped override
#![allow(unused)]
fn main() {
use std::sync::Arc;
use starweaver_agent::{AgentBuilder, TestModel};
async fn example() -> Result<(), starweaver_agent::AgentError> {
let production_agent = AgentBuilder::new(Arc::new(TestModel::with_text("prod"))).build();
let test_agent = production_agent
.override_config()
.model(Arc::new(TestModel::with_text("test")))
.build();
let result = test_agent.run("hello").await?;
assert_eq!(result.output, "test");
Ok(())
}
}
Production-request guard
#![allow(unused)]
fn main() {
use starweaver_model::block_real_model_requests;
let _guard = block_real_model_requests();
assert!(!starweaver_model::allow_real_model_requests());
}
Run validation with:
make fmt-check && make check && make test
Coverage
CI runs grouped line coverage gates with cargo-llvm-cov.
cargo install cargo-llvm-cov
make coverage-core
make coverage-agent
make coverage-service
make coverage-ci
make coverage
Default acceptance gates are 95% for core contract paths, 90% for agent SDK contract paths, and 80% for CLI/service paths. Core and agent gates also enforce measured coverage floors over their full package groups. make coverage-ci cleans and collects one workspace profile set before generating the three package-scoped gate reports. The dedicated coverage workflow reuses that collection to generate target/llvm-cov/lcov.info and upload the LCOV artifact.
Automation validation
Repository automation runs through the Rust xtask crate and Makefile targets.
make scripts-check
Model cassette workflow
Provider replay fixtures can be recorded, scrubbed, and imported through repository scripts. The workflow records a live provider response, scrubs secrets and unstable ids, then imports a deterministic replay fixture.
make record-model-cassette ARGS="request.json --provider openai_chat --output cassette.json"
make scrub-model-cassette ARGS="cassette.json --output cassette.scrubbed.json"
make import-model-cassette ARGS="cassette.scrubbed.json"
make replay-check
request.json should include the canonical request fields used by replay fixtures: model, history, and expected_provider_request. Add expected_response or expected_error before importing a replay fixture. Use --mock-response response.json for deterministic script tests and --dry-run to inspect the resolved provider request.