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: "0.8".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, and evolve --apply may mutate source files; every mutation routes through isolated validation and rollback gates."
47 .to_string(),
48 commands: vec![
49 AgentCommandSpec {
50 name: "recipes".to_string(),
51 purpose:
52 "List recipe tiers, required evidence, and executable mutation paths."
53 .to_string(),
54 mutates_source: false,
55 required_flags_for_mutation: Vec::new(),
56 primary_schema: "recipe-catalog".to_string(),
57 example: "mdx-rust --json recipes".to_string(),
58 },
59 AgentCommandSpec {
60 name: "scorecard".to_string(),
61 purpose:
62 "Build one agent briefing with map, plan, recipe catalog, readiness, and next commands."
63 .to_string(),
64 mutates_source: false,
65 required_flags_for_mutation: Vec::new(),
66 primary_schema: "evolution-scorecard".to_string(),
67 example: "mdx-rust --json scorecard src/service".to_string(),
68 },
69 AgentCommandSpec {
70 name: "evidence".to_string(),
71 purpose:
72 "Collect measured evidence profiles that control autonomous recipe depth."
73 .to_string(),
74 mutates_source: false,
75 required_flags_for_mutation: Vec::new(),
76 primary_schema: "evidence-run".to_string(),
77 example: "mdx-rust --json evidence src/service --include-coverage".to_string(),
78 },
79 AgentCommandSpec {
80 name: "map".to_string(),
81 purpose:
82 "Build a non-mutating repo intelligence map with evidence gates and risks.".to_string(),
83 mutates_source: false,
84 required_flags_for_mutation: Vec::new(),
85 primary_schema: "codebase-map".to_string(),
86 example: "mdx-rust --json map src/service".to_string(),
87 },
88 AgentCommandSpec {
89 name: "plan".to_string(),
90 purpose:
91 "Build a non-mutating refactor plan with executable and plan-only candidates."
92 .to_string(),
93 mutates_source: false,
94 required_flags_for_mutation: Vec::new(),
95 primary_schema: "refactor-plan".to_string(),
96 example: "mdx-rust --json plan src/service".to_string(),
97 },
98 AgentCommandSpec {
99 name: "evolve".to_string(),
100 purpose:
101 "Run budget-bounded autonomous improvement over evidence-allowed candidates."
102 .to_string(),
103 mutates_source: true,
104 required_flags_for_mutation: vec!["--apply".to_string()],
105 primary_schema: "autopilot-run".to_string(),
106 example:
107 "mdx-rust --json evolve src/service --budget 10m --tier 2 --min-evidence covered"
108 .to_string(),
109 },
110 AgentCommandSpec {
111 name: "apply-plan".to_string(),
112 purpose:
113 "Execute explicitly executable candidates from a saved plan after hash and staleness checks."
114 .to_string(),
115 mutates_source: true,
116 required_flags_for_mutation: vec!["--apply".to_string()],
117 primary_schema: "refactor-batch-apply-run".to_string(),
118 example: "mdx-rust --json apply-plan .mdx-rust/plans/plan.json --all".to_string(),
119 },
120 AgentCommandSpec {
121 name: "explain".to_string(),
122 purpose:
123 "Summarize an mdx-rust artifact and recommend safe next actions."
124 .to_string(),
125 mutates_source: false,
126 required_flags_for_mutation: Vec::new(),
127 primary_schema: "artifact-explanation".to_string(),
128 example: "mdx-rust --json explain .mdx-rust/plans/refactor-plan.json"
129 .to_string(),
130 },
131 AgentCommandSpec {
132 name: "schema".to_string(),
133 purpose: "Emit JSON Schema for agent-facing artifacts.".to_string(),
134 mutates_source: false,
135 required_flags_for_mutation: Vec::new(),
136 primary_schema: "json-schema".to_string(),
137 example: "mdx-rust --json schema agent-contract".to_string(),
138 },
139 ],
140 workflows: vec![
141 AgentWorkflow {
142 id: "safe-intake".to_string(),
143 goal: "Understand a Rust target before proposing code changes.".to_string(),
144 steps: vec![
145 "mdx-rust --json agent-contract".to_string(),
146 "mdx-rust --json recipes".to_string(),
147 "mdx-rust --json scorecard <target>".to_string(),
148 "mdx-rust --json evidence <target>".to_string(),
149 "mdx-rust --json map <target>".to_string(),
150 "mdx-rust --json plan <target>".to_string(),
151 ],
152 },
153 AgentWorkflow {
154 id: "covered-autonomy".to_string(),
155 goal: "Apply Tier 2 mechanical improvements only when measured coverage allows it."
156 .to_string(),
157 steps: vec![
158 "mdx-rust --json evidence <target> --include-coverage".to_string(),
159 "mdx-rust --json evolve <target> --budget 10m --tier 2 --min-evidence covered"
160 .to_string(),
161 "Review the autopilot artifact before rerunning with --apply.".to_string(),
162 ],
163 },
164 ],
165 artifact_globs: vec![
166 ".mdx-rust/evidence/*.json".to_string(),
167 ".mdx-rust/maps/*.json".to_string(),
168 ".mdx-rust/scorecards/*.json".to_string(),
169 ".mdx-rust/plans/*.json".to_string(),
170 ".mdx-rust/autopilot/*.json".to_string(),
171 ".mdx-rust/hardening/*.json".to_string(),
172 ],
173 safety_rules: vec![
174 "Treat plan and map commands as read-only.".to_string(),
175 "Never add --apply unless the user explicitly asked for mutation.".to_string(),
176 "Do not bypass min-evidence or tier restrictions.".to_string(),
177 "Re-run plan after any source file changes because stale plans are rejected.".to_string(),
178 "Use artifact_path fields as the source of truth for follow-up inspection.".to_string(),
179 ],
180 }
181}