dream-worker 0.1.0

Hook-enforced discipline for LLM coding agents: worktree isolation, tool-call budgets, TOML test plans, verification gates.
Documentation
//! Dream Worker Discipline: types for hook-enforced LLM agent governance.
//!
//! Provides serde types for the TOML test plan schema and default budget
//! constants consumed by the reference shell hooks in the sibling `hooks/`
//! directory.
//!
//! See <https://github.com/architect-minder/dream-worker> for the full
//! methodology writeup and the seven rules.

use serde::{Deserialize, Serialize};

pub const DEFAULT_IMPL_TOOL_CALL_CAP: u32 = 15;
pub const DEFAULT_RESEARCH_TOOL_CALL_CAP: u32 = 5;
pub const DEFAULT_IMPL_OUTPUT_TOKEN_CAP: u32 = 20_000;
pub const DEFAULT_RESEARCH_OUTPUT_TOKEN_CAP: u32 = 10_000;
pub const MAX_CONCURRENT_AGENTS: u32 = 2;

/// TOML plan required before dispatching any agent (Rule 5).
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Plan {
    pub agent: Agent,
    pub success: Success,
    pub budget: Budget,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Agent {
    #[serde(rename = "type")]
    pub ty: AgentType,
    pub scope: String,
}

#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum AgentType {
    Implementation,
    Research,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Success {
    #[serde(default)]
    pub compile: bool,
    #[serde(default)]
    pub tests: Vec<String>,
    #[serde(default)]
    pub visual_capture: bool,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Budget {
    pub tool_calls: u32,
    pub output_tokens: u32,
}

pub fn parse_plan(s: &str) -> Result<Plan, toml::de::Error> {
    toml::from_str(s)
}

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

    #[test]
    fn parses_reference_plan() {
        let src = r#"
[agent]
type = "implementation"
scope = "src/foo.rs:10-50"

[success]
compile = true
tests = ["tests/it::foo"]

[budget]
tool_calls = 15
output_tokens = 20000
"#;
        let p = parse_plan(src).unwrap();
        assert_eq!(p.agent.ty, AgentType::Implementation);
        assert_eq!(p.budget.tool_calls, 15);
        assert_eq!(p.budget.output_tokens, 20_000);
        assert!(p.success.compile);
        assert_eq!(p.success.tests.len(), 1);
    }

    #[test]
    fn defaults_are_documented_values() {
        assert_eq!(DEFAULT_IMPL_TOOL_CALL_CAP, 15);
        assert_eq!(DEFAULT_RESEARCH_TOOL_CALL_CAP, 5);
        assert_eq!(MAX_CONCURRENT_AGENTS, 2);
    }
}