pub fn propose(
root: &Path,
statement: &str,
title: Option<&str>,
id: Option<&str>,
today: &str,
) -> Result<Proposed, ProposeError>Expand description
Write a new intent record that says what must become true and nothing else yet (ADR 0144).
The record names no milestone and no criterion: its stage derives as declared, intent validate reports the two absences as warnings, and no issue can serve it until a person
or a later step plans it. Nothing is stored about its standing; the stage stays derived
(ADR 0070). The title defaults to the statement’s first line, the identity to the
title’s slug. An existing record is never overwritten, and the file appears whole or not
at all: it is written beside its final name and renamed into place.
use majordomus_cli::intent::{propose, ProposeError};
let root = std::env::temp_dir().join(format!("mj-propose-doc-{}", std::process::id()));
let p = propose(&root, "The UI answers within 100 ms warm", None, None, "2026-10-12").unwrap();
assert_eq!(p.id, "the-ui-answers-within-100-ms-warm");
assert_eq!(p.path, ".ai/repo/project/intents/the-ui-answers-within-100-ms-warm.yaml");
let text = std::fs::read_to_string(root.join(&p.path)).unwrap();
assert!(text.contains("milestones: []") && text.contains("satisfaction: []"));
// a second proposal of the same identity is refused, and the first record is untouched
let again = propose(&root, "something else", None, Some(p.id.as_str()), "2026-10-12");
assert!(matches!(again, Err(ProposeError::Exists(_))));
assert_eq!(std::fs::read_to_string(root.join(&p.path)).unwrap(), text);
std::fs::remove_dir_all(&root).unwrap();