Skip to main content

dream_worker/
lib.rs

1//! Dream Worker Discipline: types for hook-enforced LLM agent governance.
2//!
3//! Provides serde types for the TOML test plan schema and default budget
4//! constants consumed by the reference shell hooks in the sibling `hooks/`
5//! directory.
6//!
7//! See <https://github.com/architect-minder/dream-worker> for the full
8//! methodology writeup and the seven rules.
9
10use serde::{Deserialize, Serialize};
11
12pub const DEFAULT_IMPL_TOOL_CALL_CAP: u32 = 15;
13pub const DEFAULT_RESEARCH_TOOL_CALL_CAP: u32 = 5;
14pub const DEFAULT_IMPL_OUTPUT_TOKEN_CAP: u32 = 20_000;
15pub const DEFAULT_RESEARCH_OUTPUT_TOKEN_CAP: u32 = 10_000;
16pub const MAX_CONCURRENT_AGENTS: u32 = 2;
17
18/// TOML plan required before dispatching any agent (Rule 5).
19#[derive(Clone, Debug, Deserialize, Serialize)]
20pub struct Plan {
21    pub agent: Agent,
22    pub success: Success,
23    pub budget: Budget,
24}
25
26#[derive(Clone, Debug, Deserialize, Serialize)]
27pub struct Agent {
28    #[serde(rename = "type")]
29    pub ty: AgentType,
30    pub scope: String,
31}
32
33#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
34#[serde(rename_all = "lowercase")]
35pub enum AgentType {
36    Implementation,
37    Research,
38}
39
40#[derive(Clone, Debug, Deserialize, Serialize)]
41pub struct Success {
42    #[serde(default)]
43    pub compile: bool,
44    #[serde(default)]
45    pub tests: Vec<String>,
46    #[serde(default)]
47    pub visual_capture: bool,
48}
49
50#[derive(Clone, Debug, Deserialize, Serialize)]
51pub struct Budget {
52    pub tool_calls: u32,
53    pub output_tokens: u32,
54}
55
56pub fn parse_plan(s: &str) -> Result<Plan, toml::de::Error> {
57    toml::from_str(s)
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn parses_reference_plan() {
66        let src = r#"
67[agent]
68type = "implementation"
69scope = "src/foo.rs:10-50"
70
71[success]
72compile = true
73tests = ["tests/it::foo"]
74
75[budget]
76tool_calls = 15
77output_tokens = 20000
78"#;
79        let p = parse_plan(src).unwrap();
80        assert_eq!(p.agent.ty, AgentType::Implementation);
81        assert_eq!(p.budget.tool_calls, 15);
82        assert_eq!(p.budget.output_tokens, 20_000);
83        assert!(p.success.compile);
84        assert_eq!(p.success.tests.len(), 1);
85    }
86
87    #[test]
88    fn defaults_are_documented_values() {
89        assert_eq!(DEFAULT_IMPL_TOOL_CALL_CAP, 15);
90        assert_eq!(DEFAULT_RESEARCH_TOOL_CALL_CAP, 5);
91        assert_eq!(MAX_CONCURRENT_AGENTS, 2);
92    }
93}