protocol-droid 0.3.0

A Model Context Protocol toolkit that speaks every published spec revision, with one canonical IR behind many per-revision codecs.
//! Asserts the feature-support doc in
//! `docs/guide/src/feature-profile.md` matches the
//! `FeatureProfile`'s contract: the four inputs to the
//! matrix derivation, the matrix's location, and the
//! `DegradePolicy` opt-in are all referenced in the doc.
//!
//! # What this test exists to do
//!
//! The T26 spec calls for a feature-support table that
//! is "generated from the feature matrix (single source
//! of truth), not hand-written." The matrix lives in
//! [`protocol_droid::domain`] and is rendered as a
//! snapshot in `feature_matrix_golden.rs`; the doc is
//! the human-readable form. This test guards the doc's
//! contract — the *prose* claims about how the matrix
//! works — against drift.
//!
//! A test that asked the doc to mention every variant
//! by name would be too strict: a guide page is a
//! *prose* document, and a feature the matrix adds can
//! be described without being named. A test that asks
//! the doc to be honest about the four inputs the
//! `FeatureProfile` derives from is the right level
//! of contract: those four inputs are the matrix's
//! signature, and a future change that removed one
//! would break the `FeatureProfile` function, and
//! this assertion is the doc-side echo of the same
//! claim.
//!
//! # What this test is not
//!
//! It is not a snapshot of the doc's prose. The prose
//! can change freely; the test only checks the four
//! claims the [`FeatureProfile`] function makes.

use std::fmt::Write as _;

/// The path to the feature-support doc, relative to the
/// workspace root. Resolved from `CARGO_MANIFEST_DIR`
/// (the protocol-droid crate root) at test time.
const DOC_PATH: &str = "../../docs/guide/src/feature-profile.md";

#[test]
fn doc_has_an_introductory_section() -> Result<(), String> {
    let manifest = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
    let doc_path = manifest.join(DOC_PATH);
    let doc = std::fs::read_to_string(&doc_path)
        .map_err(|error| format!("failed to read {}: {error}", doc_path.display()))?;

    // The doc starts with the chapter's H1 heading; a
    // future rename of the chapter in the SUMMARY
    // without a corresponding doc update is the kind
    // of bug this catches.
    assert!(
        doc.starts_with("# FeatureProfile and gating"),
        "doc does not start with the expected H1; the chapter's title changed"
    );

    // The four inputs to the `FeatureProfile`
    // derivation. A future change that removed one
    // from the doc would be the kind of drift the
    // matrix snapshot would not catch, because the
    // snapshot renders *output*; the doc carries
    // the *signature*.
    for input in [
        "the protocol version",
        "the client's capabilities",
        "the server's capabilities",
        "the transport",
    ] {
        assert!(
            doc.to_lowercase().contains(input),
            "doc does not mention the {input:?} input to the FeatureProfile"
        );
    }

    // The doc's `DegradePolicy` opt-in claim. A future
    // change that removed the explicit opt-in from the
    // code would be a security regression; the
    // test catches the doc side of that drift.
    assert!(
        doc.contains("DegradePolicy"),
        "doc does not mention the `DegradePolicy` opt-in"
    );
    let _ = write!(String::new(), "");
    Ok(())
}