Skip to main content

mdx_rust_core/
agent_contract.rs

1//! Agent-facing command contract for `mdx-rust`.
2//!
3//! This artifact is intentionally small and stable enough for coding agents to
4//! inspect before deciding which CLI command to call.
5
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
10pub struct MdxAgentContract {
11    pub schema_version: String,
12    pub product_version: String,
13    pub json_mode_contract: String,
14    pub mutation_contract: String,
15    pub commands: Vec<AgentCommandSpec>,
16    pub workflows: Vec<AgentWorkflow>,
17    pub artifact_globs: Vec<String>,
18    pub safety_rules: Vec<String>,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
22pub struct AgentCommandSpec {
23    pub name: String,
24    pub purpose: String,
25    pub mutates_source: bool,
26    pub required_flags_for_mutation: Vec<String>,
27    pub primary_schema: String,
28    pub example: String,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
32pub struct AgentWorkflow {
33    pub id: String,
34    pub goal: String,
35    pub steps: Vec<String>,
36}
37
38pub fn agent_contract() -> MdxAgentContract {
39    MdxAgentContract {
40        schema_version: "1.0".to_string(),
41        product_version: env!("CARGO_PKG_VERSION").to_string(),
42        json_mode_contract:
43            "Pass --json for machine-pure stdout. Errors are emitted as structured JSON when --json is set."
44                .to_string(),
45        mutation_contract:
46            "Only improve --apply, apply-plan --apply, autopilot --apply, evolve --apply, or a runtime evolve call with apply=true and confirm_mutation=true may mutate source files; every mutation routes through isolated validation and rollback gates."
47                .to_string(),
48        commands: vec![
49            AgentCommandSpec {
50                name: "runtime".to_string(),
51                purpose:
52                    "Describe local agent runtime transports, tools, and mutation rules."
53                        .to_string(),
54                mutates_source: false,
55                required_flags_for_mutation: Vec::new(),
56                primary_schema: "agent-runtime-manifest".to_string(),
57                example: "mdx-rust --json runtime".to_string(),
58            },
59            AgentCommandSpec {
60                name: "mcp".to_string(),
61                purpose:
62                    "Run the local stdio agent tool protocol for scorecard, evidence, map, plan, explain, recipes, and gated evolve."
63                        .to_string(),
64                mutates_source: true,
65                required_flags_for_mutation: vec![
66                    "apply=true".to_string(),
67                    "confirm_mutation=true".to_string(),
68                ],
69                primary_schema: "agent-runtime-manifest".to_string(),
70                example: "mdx-rust mcp --stdio".to_string(),
71            },
72            AgentCommandSpec {
73                name: "serve".to_string(),
74                purpose:
75                    "Expose the same local agent tools over localhost HTTP for agents that prefer a socket API."
76                        .to_string(),
77                mutates_source: true,
78                required_flags_for_mutation: vec![
79                    "apply=true".to_string(),
80                    "confirm_mutation=true".to_string(),
81                ],
82                primary_schema: "agent-runtime-manifest".to_string(),
83                example: "mdx-rust serve --bind 127.0.0.1:3799 --token <token>".to_string(),
84            },
85            AgentCommandSpec {
86                name: "agent-pack".to_string(),
87                purpose:
88                    "Generate agent instruction files that teach Codex, Claude, Cursor, Aider, Goose-style, or generic tools to use mdx-rust safely."
89                        .to_string(),
90                mutates_source: false,
91                required_flags_for_mutation: Vec::new(),
92                primary_schema: "agent-pack".to_string(),
93                example: "mdx-rust --json agent-pack codex".to_string(),
94            },
95            AgentCommandSpec {
96                name: "recipes".to_string(),
97                purpose:
98                    "List recipe tiers, required evidence, and executable mutation paths."
99                        .to_string(),
100                mutates_source: false,
101                required_flags_for_mutation: Vec::new(),
102                primary_schema: "recipe-catalog".to_string(),
103                example: "mdx-rust --json recipes".to_string(),
104            },
105            AgentCommandSpec {
106                name: "scorecard".to_string(),
107                purpose:
108                    "Build one agent briefing with map, plan, recipe catalog, readiness, and next commands."
109                        .to_string(),
110                mutates_source: false,
111                required_flags_for_mutation: Vec::new(),
112                primary_schema: "evolution-scorecard".to_string(),
113                example: "mdx-rust --json scorecard src/service".to_string(),
114            },
115            AgentCommandSpec {
116                name: "agent-ready".to_string(),
117                purpose:
118                    "Return a compact readiness report for safe external-agent autonomy."
119                        .to_string(),
120                mutates_source: false,
121                required_flags_for_mutation: Vec::new(),
122                primary_schema: "agent-ready-report".to_string(),
123                example: "mdx-rust --json agent-ready src/service".to_string(),
124            },
125            AgentCommandSpec {
126                name: "evidence".to_string(),
127                purpose:
128                    "Collect measured evidence profiles that control autonomous recipe depth."
129                        .to_string(),
130                mutates_source: false,
131                required_flags_for_mutation: Vec::new(),
132                primary_schema: "evidence-run".to_string(),
133                example: "mdx-rust --json evidence src/service --include-coverage".to_string(),
134            },
135            AgentCommandSpec {
136                name: "map".to_string(),
137                purpose:
138                    "Build a non-mutating repo intelligence map with evidence gates and risks.".to_string(),
139                mutates_source: false,
140                required_flags_for_mutation: Vec::new(),
141                primary_schema: "codebase-map".to_string(),
142                example: "mdx-rust --json map src/service".to_string(),
143            },
144            AgentCommandSpec {
145                name: "plan".to_string(),
146                purpose:
147                    "Build a non-mutating refactor plan with executable and plan-only candidates."
148                        .to_string(),
149                mutates_source: false,
150                required_flags_for_mutation: Vec::new(),
151                primary_schema: "refactor-plan".to_string(),
152                example: "mdx-rust --json plan src/service".to_string(),
153            },
154            AgentCommandSpec {
155                name: "evolve".to_string(),
156                purpose:
157                    "Run budget-bounded autonomous improvement over evidence-allowed candidates."
158                        .to_string(),
159                mutates_source: true,
160                required_flags_for_mutation: vec!["--apply".to_string()],
161                primary_schema: "autopilot-run".to_string(),
162                example:
163                    "mdx-rust --json evolve src/service --budget 10m --tier 2 --min-evidence covered"
164                        .to_string(),
165            },
166            AgentCommandSpec {
167                name: "apply-plan".to_string(),
168                purpose:
169                    "Execute explicitly executable candidates from a saved plan after hash and staleness checks."
170                        .to_string(),
171                mutates_source: true,
172                required_flags_for_mutation: vec!["--apply".to_string()],
173                primary_schema: "refactor-batch-apply-run".to_string(),
174                example: "mdx-rust --json apply-plan .mdx-rust/plans/plan.json --all".to_string(),
175            },
176            AgentCommandSpec {
177                name: "explain".to_string(),
178                purpose:
179                    "Summarize an mdx-rust artifact and recommend safe next actions."
180                        .to_string(),
181                mutates_source: false,
182                required_flags_for_mutation: Vec::new(),
183                primary_schema: "artifact-explanation".to_string(),
184                example: "mdx-rust --json explain .mdx-rust/plans/refactor-plan.json"
185                    .to_string(),
186            },
187            AgentCommandSpec {
188                name: "schema".to_string(),
189                purpose: "Emit JSON Schema for agent-facing artifacts.".to_string(),
190                mutates_source: false,
191                required_flags_for_mutation: Vec::new(),
192                primary_schema: "json-schema".to_string(),
193                example: "mdx-rust --json schema agent-contract".to_string(),
194            },
195        ],
196        workflows: vec![
197            AgentWorkflow {
198                id: "safe-intake".to_string(),
199                goal: "Understand a Rust target before proposing code changes.".to_string(),
200                steps: vec![
201                    "mdx-rust --json agent-contract".to_string(),
202                    "mdx-rust --json runtime".to_string(),
203                    "mdx-rust --json recipes".to_string(),
204                    "mdx-rust --json agent-ready <target>".to_string(),
205                    "mdx-rust --json scorecard <target>".to_string(),
206                    "mdx-rust --json evidence <target>".to_string(),
207                    "mdx-rust --json map <target>".to_string(),
208                    "mdx-rust --json plan <target>".to_string(),
209                ],
210            },
211            AgentWorkflow {
212                id: "agent-runtime".to_string(),
213                goal: "Let an external coding agent call mdx-rust through a local runtime surface.".to_string(),
214                steps: vec![
215                    "mdx-rust --json runtime".to_string(),
216                    "mdx-rust mcp --stdio".to_string(),
217                    "Call tools/list before tools/call.".to_string(),
218                    "Only call mutation-capable tools with apply=true and confirm_mutation=true after human approval.".to_string(),
219                ],
220            },
221            AgentWorkflow {
222                id: "covered-autonomy".to_string(),
223                goal: "Apply Tier 2 mechanical improvements only when measured coverage allows it."
224                    .to_string(),
225                steps: vec![
226                    "mdx-rust --json evidence <target> --include-coverage".to_string(),
227                    "mdx-rust --json evolve <target> --budget 10m --tier 2 --min-evidence covered"
228                        .to_string(),
229                    "Review the autopilot artifact before rerunning with --apply.".to_string(),
230                ],
231            },
232        ],
233        artifact_globs: vec![
234            ".mdx-rust/evidence/*.json".to_string(),
235            ".mdx-rust/maps/*.json".to_string(),
236            ".mdx-rust/scorecards/*.json".to_string(),
237            ".mdx-rust/plans/*.json".to_string(),
238            ".mdx-rust/autopilot/*.json".to_string(),
239            ".mdx-rust/hardening/*.json".to_string(),
240            ".mdx-rust/agent-pack/*".to_string(),
241        ],
242        safety_rules: vec![
243            "Treat plan and map commands as read-only.".to_string(),
244            "Never add --apply unless the user explicitly asked for mutation.".to_string(),
245            "Runtime evolve calls with apply=true must also include confirm_mutation=true.".to_string(),
246            "Do not bypass min-evidence or tier restrictions.".to_string(),
247            "Re-run plan after any source file changes because stale plans are rejected.".to_string(),
248            "Treat localhost HTTP as a local developer surface, not a remote multi-tenant service.".to_string(),
249            "Use artifact_path fields as the source of truth for follow-up inspection.".to_string(),
250        ],
251    }
252}