1use 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}