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.7".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: "evidence".to_string(),
51 purpose:
52 "Collect measured evidence that controls autonomous recipe depth.".to_string(),
53 mutates_source: false,
54 required_flags_for_mutation: Vec::new(),
55 primary_schema: "evidence-run".to_string(),
56 example: "mdx-rust --json evidence src/service --include-coverage".to_string(),
57 },
58 AgentCommandSpec {
59 name: "map".to_string(),
60 purpose:
61 "Build a non-mutating repo intelligence map with evidence gates and risks.".to_string(),
62 mutates_source: false,
63 required_flags_for_mutation: Vec::new(),
64 primary_schema: "codebase-map".to_string(),
65 example: "mdx-rust --json map src/service".to_string(),
66 },
67 AgentCommandSpec {
68 name: "plan".to_string(),
69 purpose:
70 "Build a non-mutating refactor plan with executable and plan-only candidates."
71 .to_string(),
72 mutates_source: false,
73 required_flags_for_mutation: Vec::new(),
74 primary_schema: "refactor-plan".to_string(),
75 example: "mdx-rust --json plan src/service".to_string(),
76 },
77 AgentCommandSpec {
78 name: "evolve".to_string(),
79 purpose:
80 "Run budget-bounded autonomous improvement over evidence-allowed candidates."
81 .to_string(),
82 mutates_source: true,
83 required_flags_for_mutation: vec!["--apply".to_string()],
84 primary_schema: "autopilot-run".to_string(),
85 example:
86 "mdx-rust --json evolve src/service --budget 10m --tier 2 --min-evidence covered"
87 .to_string(),
88 },
89 AgentCommandSpec {
90 name: "apply-plan".to_string(),
91 purpose:
92 "Execute explicitly executable candidates from a saved plan after hash and staleness checks."
93 .to_string(),
94 mutates_source: true,
95 required_flags_for_mutation: vec!["--apply".to_string()],
96 primary_schema: "refactor-batch-apply-run".to_string(),
97 example: "mdx-rust --json apply-plan .mdx-rust/plans/plan.json --all".to_string(),
98 },
99 AgentCommandSpec {
100 name: "schema".to_string(),
101 purpose: "Emit JSON Schema for agent-facing artifacts.".to_string(),
102 mutates_source: false,
103 required_flags_for_mutation: Vec::new(),
104 primary_schema: "json-schema".to_string(),
105 example: "mdx-rust --json schema agent-contract".to_string(),
106 },
107 ],
108 workflows: vec![
109 AgentWorkflow {
110 id: "safe-intake".to_string(),
111 goal: "Understand a Rust target before proposing code changes.".to_string(),
112 steps: vec![
113 "mdx-rust --json agent-contract".to_string(),
114 "mdx-rust --json evidence <target>".to_string(),
115 "mdx-rust --json map <target>".to_string(),
116 "mdx-rust --json plan <target>".to_string(),
117 ],
118 },
119 AgentWorkflow {
120 id: "covered-autonomy".to_string(),
121 goal: "Apply Tier 2 mechanical improvements only when measured coverage allows it."
122 .to_string(),
123 steps: vec![
124 "mdx-rust --json evidence <target> --include-coverage".to_string(),
125 "mdx-rust --json evolve <target> --budget 10m --tier 2 --min-evidence covered"
126 .to_string(),
127 "Review the autopilot artifact before rerunning with --apply.".to_string(),
128 ],
129 },
130 ],
131 artifact_globs: vec![
132 ".mdx-rust/evidence/*.json".to_string(),
133 ".mdx-rust/maps/*.json".to_string(),
134 ".mdx-rust/plans/*.json".to_string(),
135 ".mdx-rust/autopilot/*.json".to_string(),
136 ".mdx-rust/hardening/*.json".to_string(),
137 ],
138 safety_rules: vec![
139 "Treat plan and map commands as read-only.".to_string(),
140 "Never add --apply unless the user explicitly asked for mutation.".to_string(),
141 "Do not bypass min-evidence or tier restrictions.".to_string(),
142 "Re-run plan after any source file changes because stale plans are rejected.".to_string(),
143 "Use artifact_path fields as the source of truth for follow-up inspection.".to_string(),
144 ],
145 }
146}