Skip to main content

ainl_impact_policy/
lib.rs

1//! [`RecommendedNextTools`](ainl_contracts::RecommendedNextTools) state machine for MCP responses.
2
3use ainl_contracts::{RecommendedNextTools, RecommendedToolStep, CONTRACT_SCHEMA_VERSION};
4
5/// Phase of the authoring loop.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum AuthoringPhase {
8    AfterEdit,
9    AfterValidateOk,
10    AfterCompileOk,
11    AfterImpactOk,
12    ReadyToRun,
13}
14
15/// Build next tools from phase (deterministic).
16#[must_use]
17pub fn recommend_next_tools(phase: AuthoringPhase, strict_impact: bool) -> RecommendedNextTools {
18    let mut steps: Vec<RecommendedToolStep> = Vec::new();
19    match phase {
20        AuthoringPhase::AfterEdit => {
21            steps.push(step("ainl_validate", "Validate before compile"));
22        }
23        AuthoringPhase::AfterValidateOk => {
24            steps.push(step("ainl_compile", "IR for diff/impact"));
25            if strict_impact {
26                steps.push(step(
27                    "ainl_ir_diff",
28                    "Compare IR vs previous (impact awareness)",
29                ));
30            }
31        }
32        AuthoringPhase::AfterCompileOk => {
33            if strict_impact {
34                steps.push(step("ainl_ir_diff", "Confirm blast radius on IR delta"));
35            }
36            steps.push(step("ainl_run", "Execute with registered adapters"));
37        }
38        AuthoringPhase::AfterImpactOk => {
39            steps.push(step("ainl_run", "Execute"));
40        }
41        AuthoringPhase::ReadyToRun => {
42            steps.push(step("ainl_run", "Execute"));
43        }
44    }
45    RecommendedNextTools {
46        schema_version: CONTRACT_SCHEMA_VERSION,
47        steps,
48    }
49}
50
51fn step(tool: &str, reason: &str) -> RecommendedToolStep {
52    RecommendedToolStep {
53        tool: tool.to_string(),
54        reason: Some(reason.to_string()),
55    }
56}
57
58/// Full golden chain for docs and MCP resources.
59#[must_use]
60pub fn golden_chain() -> RecommendedNextTools {
61    RecommendedNextTools::golden_default_chain()
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn after_edit_requests_validate() {
70        let r = recommend_next_tools(AuthoringPhase::AfterEdit, false);
71        assert_eq!(
72            r.steps.first().map(|s| s.tool.as_str()),
73            Some("ainl_validate")
74        );
75    }
76}