ainl-contracts 0.1.4

Shared policy contracts for repo intelligence, context freshness, and impact-first tooling (no OpenFang deps)
Documentation
//! Cross-language schema conformance: Rust serde round-trip for mission substrate types.

use ainl_contracts::{
    Assertion, AssertionId, AssertionState, Feature, FeatureId, FeatureStatus, Handoff,
    HandoffTests, HandoffVerification, Mission, MissionCapabilityFlags, MissionId, MissionState,
    SkillFeedback, VerificationStep,
};
use chrono::Utc;

#[test]
fn mission_json_roundtrip() {
    let mission = Mission {
        mission_id: MissionId("mission-test-001".into()),
        objective_md: "Ship mission substrate Phase 0.".into(),
        state: MissionState::AwaitingInput,
        milestone_ids: vec!["m1".into()],
        mission_root: Some("/tmp/mission-root".into()),
        created_at: Utc::now(),
        last_orchestrator_turn_at: None,
        capability_flags: MissionCapabilityFlags {
            coding_domain: Some(true),
            auto_remediation: None,
        },
    };
    let json = serde_json::to_string(&mission).expect("serialize mission");
    let back: Mission = serde_json::from_str(&json).expect("deserialize mission");
    assert_eq!(back.mission_id.as_str(), "mission-test-001");
    assert_eq!(back.state, MissionState::AwaitingInput);
}

#[test]
fn feature_and_handoff_json_roundtrip() {
    let feature = Feature {
        feature_id: FeatureId("feat-a".into()),
        description: "First feature".into(),
        status: FeatureStatus::Pending,
        milestone: Some("m1".into()),
        skill_name: Some("coding-agent".into()),
        touches_files: vec!["src/".into()],
        preconditions: vec![],
        expected_behavior: vec!["A works".into()],
        verification_steps: vec![VerificationStep::ShellCommand {
            cmd: "pytest -q".into(),
            expected_exit_code: 0,
        }],
        fulfills: vec![AssertionId("assert-a".into())],
        snapshot: None,
    };
    let feature_json = serde_json::to_string(&feature).expect("feature serialize");
    let _: Feature = serde_json::from_str(&feature_json).expect("feature deserialize");

    let handoff = Handoff {
        feature_id: FeatureId("feat-a".into()),
        agent_id: "agent-1".into(),
        salient_summary: "Summary".into(),
        what_was_implemented_md: "Implemented A".into(),
        what_was_left_undone_md: String::new(),
        verification: HandoffVerification::default(),
        tests: HandoffTests::default(),
        discovered_issues: vec![],
        skill_feedback: SkillFeedback {
            suggested_changes: vec!["Add retry guard".into()],
            ..Default::default()
        },
    };
    let handoff_json = serde_json::to_string(&handoff).expect("handoff serialize");
    let _: Handoff = serde_json::from_str(&handoff_json).expect("handoff deserialize");
}

#[test]
fn assertion_json_roundtrip() {
    let assertion = Assertion {
        assertion_id: AssertionId("assert-a".into()),
        description: "A passes".into(),
        verification_steps: vec![VerificationStep::ShellCommand {
            cmd: "pytest tests/test_a.py".into(),
            expected_exit_code: 0,
        }],
        state: AssertionState::Pending,
        milestone: Some("m1".into()),
        failed_count: 0,
    };
    let json = serde_json::to_string(&assertion).expect("assertion serialize");
    let back: Assertion = serde_json::from_str(&json).expect("assertion deserialize");
    assert_eq!(back.assertion_id.as_str(), "assert-a");
}