pub mod agents;
pub mod config_validation;
pub mod context;
pub mod dcp;
pub mod dx_integration;
pub mod emitter;
pub mod error;
pub mod format;
pub mod generator_integration;
pub mod hooks;
pub mod integration;
pub mod modules;
pub mod parser;
pub mod scale;
pub mod steering;
pub mod strategy;
pub mod sync;
pub mod sysinfo;
pub mod templates;
pub mod validation;
pub mod workflows;
pub mod binary;
pub mod fusion;
pub mod security;
pub mod state;
pub mod streaming;
#[cfg(feature = "cli")]
pub mod cli;
pub use context::{ProjectAnalyzer, ProjectContext};
pub use emitter::Emitter;
pub use format::{DrvDecoder, DrvEncoder, DrvHeader, RuleCategory};
pub use parser::{ParsedRule, Parser, UnifiedRule};
pub use sync::SyncEngine;
pub use templates::{Template, TemplateRegistry};
pub use validation::{Linter, ValidationResult};
pub use binary::{
Blake3Checksum, InfinityHeader, InfinityRule, MappedRule, SimdTokenizer, StringId, StringTable,
StringTableBuilder,
};
pub use fusion::{BinaryCache, FusionModule, HotCache, SpeculativeLoader};
pub use security::{Capability, CapabilityManifest, Ed25519Signer, IntegrityGuard, Sandbox};
pub use state::{AtomicSync, DirtyBits, RuleSnapshot, SharedRules, SnapshotManager};
pub use streaming::{ChunkStreamer, ETagNegotiator, HtipDelivery, XorPatcher};
pub use dx_integration::DxSerializable;
pub use dx_integration::{
DxDocumentable, DxMarkdownConfig, DxMarkdownFormat, rules_to_dx_markdown,
};
pub use dx_integration::{LegacyConverter, LegacyFormat, LegacySerializable};
pub use dcp::{ConnectionState, DcpClient, DcpConfig, ToolDefinition};
pub use generator_integration::{
DrivenTemplate, DrivenTemplateProvider, DrivenTemplateType, GenerateParams, GeneratedFile,
GeneratorBridge, TemplateCategory, TemplateInfo,
};
pub use integration::{
BinaryFormatChecker, CrossCrateHeader, DrivenDcpBridge, DrivenTool, DrivenToolCategory,
HookMessage, HookMessenger, SourceCrate, SpecScaffoldResult, SpecScaffolder,
ValidationResult as IntegrationValidationResult,
};
pub use error::{EnhancedError, EnhancedResult, ErrorContext};
pub use config_validation::{
ConfigValidator, ValidationError, ValidationReport, ValidationWarning, validate_config,
};
pub use hooks::{
AgentHook, BuildEvent, GitOp, HookAction, HookCondition, HookContext, HookEngine,
HookExecutionResult, HookTrigger, TestFilter, TestResult, TestStatus,
};
pub use steering::{AgentContext, FileReference, SteeringEngine, SteeringInclusion, SteeringRule};
pub use strategy::{
ClaimId, ClaimStatus, ClaimToken, CommandEvidence, CommandProof, CommandStatus, FileProof,
GitCheckoutKind, LaneClaim, LaneId, LanePassAssignment, LanePassAssignmentStatus,
LanePassConfig, LanePassStatePaths, LanePassStore, NextPassHandoff, OutcomeProof, PassNumber,
PassOutcome, ProofReceipt, ReceiptFormat, SubagentDelegation, VerificationClass, WorkerId,
WorkerIdentity, WorkerKind, WorktreeCreationDecision, WorktreeIsolationMode,
WorktreeIsolationPlan, WorktreeMetadata, detect_worktree_metadata, plan_worktree_isolation,
};
pub use sysinfo::{
BuildToolInfo, GitInfo, LanguageInfo, OsInfo, PackageManagerInfo, ProjectInfo, ProjectType,
ShellInfo, SystemInfo, SystemInfoCache, SystemInfoProvider, TestFrameworkInfo,
};
pub use agents::{Agent, AgentPersona, AgentRegistry, DelegationRequest, DelegationResult};
pub use workflows::{
StepResult, Workflow, WorkflowBranch, WorkflowEngine, WorkflowPhase, WorkflowProgress,
WorkflowSession, WorkflowStep,
};
pub use scale::{
ComplexityAnalyzer, DependencyAnalyzer, FileSizeAnalyzer, HistoryAnalyzer,
ProjectContext as ScaleProjectContext, ProjectScale, ScaleAnalyzer, ScaleDetector,
ScaleRecommendation, TeamSizeAnalyzer,
};
pub use modules::{Module, ModuleDependency, ModuleManager, ModuleStatus};
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct DrivenConfig {
pub version: String,
pub default_editor: Editor,
pub editors: EditorConfig,
pub templates: TemplateConfig,
pub sync: SyncConfig,
pub context: ContextConfig,
}
impl Default for DrivenConfig {
fn default() -> Self {
Self {
version: "1.0".to_string(),
default_editor: Editor::Cursor,
editors: EditorConfig::default(),
templates: TemplateConfig::default(),
sync: SyncConfig::default(),
context: ContextConfig::default(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Editor {
Cursor,
Copilot,
Windsurf,
Claude,
Aider,
Cline,
}
impl std::fmt::Display for Editor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.display_name())
}
}
impl Editor {
pub fn rule_path(&self) -> &'static str {
match self {
Editor::Cursor => ".cursorrules",
Editor::Copilot => ".github/copilot-instructions.md",
Editor::Windsurf => ".windsurfrules",
Editor::Claude => ".claude/settings.json",
Editor::Aider => ".aider.conf.yml",
Editor::Cline => ".cline/settings.json",
}
}
pub fn display_name(&self) -> &'static str {
match self {
Editor::Cursor => "Cursor",
Editor::Copilot => "GitHub Copilot",
Editor::Windsurf => "Windsurf",
Editor::Claude => "Claude Code",
Editor::Aider => "Aider",
Editor::Cline => "Cline",
}
}
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct EditorConfig {
pub cursor: bool,
pub copilot: bool,
pub windsurf: bool,
pub claude: bool,
pub aider: bool,
pub cline: bool,
}
impl Default for EditorConfig {
fn default() -> Self {
Self {
cursor: true,
copilot: true,
windsurf: false,
claude: true,
aider: false,
cline: false,
}
}
}
#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
pub struct TemplateConfig {
pub personas: Vec<String>,
pub project: Option<String>,
pub standards: Vec<String>,
pub workflow: Option<String>,
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct SyncConfig {
pub watch: bool,
pub auto_convert: bool,
pub source_of_truth: String,
}
impl Default for SyncConfig {
fn default() -> Self {
Self {
watch: true,
auto_convert: true,
source_of_truth: ".driven/rules.drv".to_string(),
}
}
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct ContextConfig {
pub include: Vec<String>,
pub exclude: Vec<String>,
pub index_path: String,
}
impl Default for ContextConfig {
fn default() -> Self {
Self {
include: vec!["src/**".to_string(), "crates/**".to_string()],
exclude: vec!["target/**".to_string(), "node_modules/**".to_string()],
index_path: ".driven/index.drv".to_string(),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct RuleSet {
pub rules: Vec<UnifiedRule>,
pub source: Option<std::path::PathBuf>,
}
impl RuleSet {
pub fn new() -> Self {
Self::default()
}
pub fn load(path: impl AsRef<std::path::Path>) -> Result<Self> {
let path = path.as_ref();
let parser = Parser::detect(path)?;
let rules = parser.parse_file(path)?;
Ok(Self {
rules,
source: Some(path.to_path_buf()),
})
}
pub fn load_binary(path: impl AsRef<std::path::Path>) -> Result<Self> {
let data = std::fs::read(path.as_ref())?;
let decoder = DrvDecoder::new(&data)?;
let rules = decoder.decode_all()?;
Ok(Self {
rules,
source: Some(path.as_ref().to_path_buf()),
})
}
pub fn save_binary(&self, path: impl AsRef<std::path::Path>) -> Result<()> {
let encoder = DrvEncoder::new();
let data = encoder.encode(&self.rules)?;
std::fs::write(path, data)?;
Ok(())
}
pub fn emit(&self, editor: Editor, path: impl AsRef<std::path::Path>) -> Result<()> {
let emitter = Emitter::for_editor(editor);
emitter.emit(&self.rules, path)?;
Ok(())
}
pub fn emit_cursor(&self, path: impl AsRef<std::path::Path>) -> Result<()> {
self.emit(Editor::Cursor, path)
}
pub fn emit_copilot(&self, path: impl AsRef<std::path::Path>) -> Result<()> {
self.emit(Editor::Copilot, path)
}
pub fn emit_windsurf(&self, path: impl AsRef<std::path::Path>) -> Result<()> {
self.emit(Editor::Windsurf, path)
}
pub fn len(&self) -> usize {
self.rules.len()
}
pub fn is_empty(&self) -> bool {
self.rules.is_empty()
}
pub fn as_unified(&self) -> Vec<UnifiedRule> {
self.rules.clone()
}
}
#[derive(Debug, thiserror::Error)]
pub enum DrivenError {
#[error("IO error: {0}")]
Io(std::io::Error),
#[error("Parse error: {0}")]
Parse(String),
#[error("Format error: {0}")]
Format(String),
#[error("Invalid binary format: {0}")]
InvalidBinary(String),
#[error("Template error: {0}")]
Template(String),
#[error("Template not found: {0}")]
TemplateNotFound(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Sync error: {0}")]
Sync(String),
#[error("Config error: {0}")]
Config(String),
#[error("Security error: {0}")]
Security(String),
#[error("Context error: {0}")]
Context(String),
#[error("CLI error: {0}")]
Cli(String),
#[error("Unsupported format: {0}")]
UnsupportedFormat(String),
}
pub type Result<T> = std::result::Result<T, DrivenError>;
impl From<std::io::Error> for DrivenError {
fn from(err: std::io::Error) -> Self {
DrivenError::Io(err)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = DrivenConfig::default();
assert_eq!(config.version, "1.0");
assert_eq!(config.default_editor, Editor::Cursor);
assert!(config.editors.cursor);
assert!(config.editors.copilot);
}
#[test]
fn test_editor_paths() {
assert_eq!(Editor::Cursor.rule_path(), ".cursorrules");
assert_eq!(
Editor::Copilot.rule_path(),
".github/copilot-instructions.md"
);
assert_eq!(Editor::Windsurf.rule_path(), ".windsurfrules");
}
#[test]
fn test_empty_ruleset() {
let rules = RuleSet::new();
assert!(rules.rules.is_empty());
assert!(rules.source.is_none());
}
}