//! Regression pin: the effect-system documentation must stay true.
//!
//! Three load-bearing effect claims were fiction until the
//! 2026-05-16 effect-doc-honesty tidy: a non-existent
//! row-polymorphic effect row, `Diverge` advertised as a wired-up
//! built-in op (zero code in any crate), and a `Term::Do`
//! doc-comment naming a non-existent link-time effect-handler
//! table. This pin fails if any of the fiction strings reappears
//! or any corrected anchor is dropped.

use std::fs;

fn read(rel: &str) -> String {
    let p = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
    fs::read_to_string(format!("{p}{rel}"))
        .unwrap_or_else(|e| panic!("read {rel}: {e}"))
}

/// Collapse every whitespace run to a single space so a pinned phrase
/// split across the design/ files' hard line-wrap (or across the
/// join seam) still matches a single-line assertion substring.
fn norm(s: &str) -> String {
    s.split_whitespace().collect::<Vec<_>>().join(" ")
}

#[test]
fn design_md_effect_prose_is_true() {
    // Effect prose -> design/models/0002-effects.md; the
    // "the built-in IO and Diverge ops" absent-pin's home
    // `## What is not (yet) supported` -> design/contracts/0010-scope-boundaries.md.
    let d = norm(&[read("design/models/0002-effects.md"),
                   read("design/contracts/0010-scope-boundaries.md")].join("\n"));
    // fiction absent
    assert!(!d.contains("row-polymorphic"),
        "design/: the effect row is NOT row-polymorphic (no EffectRow / row var exists)");
    assert!(!d.contains("`IO` and `Diverge` (for infinite"),
        "design/: `Diverge` is not a wired-up MVP effect");
    assert!(!d.contains("the built-in IO and Diverge ops"),
        "design/contracts/0010-scope-boundaries.md: there is no built-in Diverge op");
    // corrected anchors present
    assert!(d.contains("flat, unordered, closed set of effect names"),
        "design/models/0002-effects.md Decision 3 must describe the real (flat set-equality) effect model");
    assert!(d.contains("`Diverge` (for non-termination) is reserved"),
        "design/models/0002-effects.md Decision 3 must state Diverge is reserved/unimplemented");
}

#[test]
fn term_do_doc_comment_is_true() {
    let a = read("crates/ailang-core/src/ast.rs");
    assert!(!a.contains("resolved against the effect-handler table at link time"),
        "ast.rs Term::Do: there is no effect-handler table and no link-time resolution");
    assert!(a.contains("resolved at typecheck against `Env::effect_ops`"),
        "ast.rs Term::Do doc must describe the real resolution mechanism");
}

#[test]
fn form_a_spec_effect_names_are_true() {
    let f = read("crates/ailang-core/specs/form_a.md");
    assert!(!f.contains("`Diverge` for `diverge/*`"),
        "form_a.md: there is no `diverge/*` op namespace");
    assert!(!f.contains("currently `IO` and `Diverge`"),
        "form_a.md: `Diverge` is reserved, not a currently-usable effect");
    assert!(f.contains("The only built-in effect op is `io/print_str`"),
        "form_a.md rule 3 must name the real single built-in effect op");
}

#[test]
fn merge_prose_contract_example_is_true() {
    let m = read("crates/ail/src/main.rs");
    assert!(!m.contains("`(effects Diverge)`"),
        "main.rs CONTRACT: do not use a non-existent effect as the example");
}
