intents.propose
Write a new intent record under `.ai/repo/project/intents/` from a statement of what must become true, with an optional title (the statement's first line when absent) and id (the title's slug when absent). The record names no milestone, criterion or invariant: its stage derives as `declared`, `intent validate` reports the two absences as warnings rather than failures, and no work can serve it until it is planned (ADR 0144). Nothing about its standing is stored. An existing record is refused, never overwritten, and the file appears whole or not at all. The answer names the identity and the file; `intents.record` answers the derived stage once the index holds it.
Write a new intent record under `.ai/repo/project/intents/` from a statement of what must become true, with an optional title (the statement's first line when absent) and id (the title's slug when absent). The record names no milestone, criterion or invariant: its stage derives as `declared`, `intent validate` reports the two absences as warnings rather than failures, and no work can serve it until it is planned (ADR 0144). Nothing about its standing is stored. An existing record is refused, never overwritten, and the file appears whole or not at all. The answer names the identity and the file; `intents.record` answers the derived stage once the index holds it.
- command
- experimental
- module intents
- #intent
- #project
Exposure
Where this one definition is reachable. Absence is explicit: a surface not listed does not carry it.
| surface | as |
|---|---|
| MCP | tool majordomus_intent_propose |
| HTTP | POST /api/v1/intents/propose operationId intents.propose |
| command line | majordomus intent propose |
Schemas
The canonical input and output, from the Rust types; the MCP tool schema and the OpenAPI parameters and responses are derived from these.
input · IntentProposeInput
intents.propose: what must become true, and optionally its title and id.
No milestone, criterion or invariant: a proposal says what is wanted, and planning it is a separate act (ADR 0144). No timestamp either: the record is dated when it is written.
use majordomus_cli::capability::builtin::intents::IntentProposeInput;
let i: IntentProposeInput =
serde_json::from_str(r#"{"statement": "The UI answers within 100 ms warm"}"#).unwrap();
assert_eq!(i.title, None);
// a field the input does not have is refused, never ignored
assert!(serde_json::from_str::<IntentProposeInput>(r#"{"statement": "s", "stage": "x"}"#).is_err());| property | type | required | description |
|---|---|---|---|
| id | string | null | no | The identity and file name; the title's slug when absent. |
| statement | string | yes | What must become true, in the proposer's words; kept verbatim. |
| title | string | null | no | One line naming it; the statement's first line when absent. |
JSON Schema
{
"additionalProperties": false,
"description": "The input of `intents.propose`: what must become true, and optionally its title and id.\n\nNo milestone, criterion or invariant: a proposal says what is wanted, and planning it is a\nseparate act (ADR 0144). No timestamp either: the record is dated when it is written.\n\n```\nuse majordomus_cli::capability::builtin::intents::IntentProposeInput;\nlet i: IntentProposeInput =\n serde_json::from_str(r#\"{\"statement\": \"The UI answers within 100 ms warm\"}\"#).unwrap();\nassert_eq!(i.title, None);\n// a field the input does not have is refused, never ignored\nassert!(serde_json::from_str::<IntentProposeInput>(r#\"{\"statement\": \"s\", \"stage\": \"x\"}\"#).is_err());\n```",
"properties": {
"id": {
"description": "The identity and file name; the title's slug when absent.",
"type": [
"string",
"null"
]
},
"statement": {
"description": "What must become true, in the proposer's words; kept verbatim.",
"type": "string"
},
"title": {
"description": "One line naming it; the statement's first line when absent.",
"type": [
"string",
"null"
]
}
},
"required": [
"statement"
],
"title": "IntentProposeInput",
"type": "object"
}output · Proposed
propose wrote: the identity, the file, and the record as it now reads.
use majordomus_cli::intent::Proposed;
let p: Proposed = serde_json::from_str(
r#"{"id": "fast-ui", "path": ".ai/repo/project/intents/fast-ui.yaml",
"title": "Fast UI", "statement": "The UI answers at once"}"#,
)
.unwrap();
// the path is the identity under the intents directory: one answer to where it lives
assert_eq!(p.path, format!(".ai/repo/project/intents/{}.yaml", p.id));| property | type | required | description |
|---|---|---|---|
| id | string | yes | The identity, which is also the file name. |
| path | string | yes | Repository-relative path of the record written. |
| statement | string | yes | What must become true, as it was given. |
| title | string | yes | One line. |
JSON Schema
{
"description": "What `propose` wrote: the identity, the file, and the record as it now reads.\n\n```\nuse majordomus_cli::intent::Proposed;\nlet p: Proposed = serde_json::from_str(\n r#\"{\"id\": \"fast-ui\", \"path\": \".ai/repo/project/intents/fast-ui.yaml\",\n \"title\": \"Fast UI\", \"statement\": \"The UI answers at once\"}\"#,\n)\n.unwrap();\n// the path is the identity under the intents directory: one answer to where it lives\nassert_eq!(p.path, format!(\".ai/repo/project/intents/{}.yaml\", p.id));\n```",
"properties": {
"id": {
"description": "The identity, which is also the file name.",
"type": "string"
},
"path": {
"description": "Repository-relative path of the record written.",
"type": "string"
},
"statement": {
"description": "What must become true, as it was given.",
"type": "string"
},
"title": {
"description": "One line.",
"type": "string"
}
},
"required": [
"id",
"path",
"title",
"statement"
],
"title": "Proposed",
"type": "object"
}Policies
- benchmark
- waived — waived: destructive
- cache
- disabled — every call runs the handler
Benchmark targets
Derived from the registry for this repository: one requirement per transport, and the cases the input type provides. The whole matrix is on the benchmarks page.
| transport | state | cases | targets |
|---|---|---|---|
| direct | waived (destructive) | 0 | |
| mcp | waived (destructive) | 0 | |
| http | waived (destructive) | 0 |