yog 0.0.51

yog: the standalone server for litany loops — the world, the balls and the conversations, behind one wire
Documentation
//! The argv seat's help (bl-52ed): what each shape answers, what it refuses to
//! answer *for* a namespace, and the narrowness of the discovery probe. The
//! zero-side-effect half — that no command composes, spawns, parks or writes on
//! the way to its page — is proved per namespace in `tests/multiplex_bl.rs`
//! (the `bl` arm's shim converge) and `src/bz_host/tests.rs` (the wall gate),
//! each of which owns the env the effect would land in.

use super::*;

fn argv(parts: &[&str]) -> Vec<String> {
    parts.iter().map(|s| (*s).to_string()).collect()
}

/// The top level is a command, in all three spellings, and its page is the
/// whole surface.
#[test]
fn the_top_level_answers_help_with_the_roster() {
    for spelling in ["--help", "-h", "help"] {
        let page = answer(&argv(&["yog", spelling])).unwrap_or_default();
        assert!(page.contains("Commands:"), "{spelling}: {page}");
    }
}

/// Higher-order in both directions: `yog help <command>` asks about a command
/// from the top, and `yog <command> --help` asks about it at the command. Same
/// question, same page.
#[test]
fn a_command_is_asked_about_from_either_end() {
    let subcmd = crate::world::hatch::EXEC_SUBCMD;
    let from_top = answer(&argv(&["yog", "help", subcmd]));
    let at_command = answer(&argv(&["yog", subcmd, "--help"]));
    assert_eq!(from_top, at_command);
    assert!(
        from_top.unwrap_or_default().contains("--cwd"),
        "the page is `exec`'s own"
    );
    assert_eq!(
        answer(&argv(&["yog", subcmd, "-h"])),
        at_command,
        "-h is the same ask"
    );
}

/// Every one of yog's own subcommands answers — including the two that used to
/// do their work first (`env` printed exports, `exec` tried to spawn a program
/// called `--help`) and the one that waited on stdin (`tool-control`). The
/// roster is derived from [`COMMANDS`] minus the [`SELF_ANSWERING`] set — the
/// authoritative definitions — so a later command cannot fall outside the
/// invariant silently, which is how `tool-host` regressed bl-52ed before the
/// severance took that verb out of this crate.
#[test]
fn every_yog_subcommand_answers_at_the_command() {
    let owed: Vec<&str> = COMMANDS
        .iter()
        .map(|row| row.verb)
        .filter(|verb| {
            !super::super::Namespace::from_arg(verb).is_some_and(super::super::Namespace::owns_argv)
        })
        .collect();
    assert!(!owed.is_empty(), "the roster derived nothing");
    for verb in owed {
        let page = answer(&argv(&["yog", verb, "--help"])).unwrap_or_default();
        assert!(page.starts_with(&format!("yog {verb}")), "{verb}: {page}");
    }
}

/// A namespace's argv belongs to the tool, so the ask passes through to the arm
/// and the tool prints its own page — yog never answers over it.
#[test]
fn a_namespace_help_is_the_tools_own_and_falls_through() {
    // The roster is derived from the router's own table and its exhaustive
    // owns_argv classification (bl-4667), so a namespace added later is
    // judged here without this list being touched.
    for (word, namespace) in super::super::namespace::NAMESPACES {
        if namespace.owns_argv() {
            assert_eq!(answer(&argv(&["yog", word, "--help"])), None, "{word}");
        } else {
            let page = answer(&argv(&["yog", word, "--help"])).unwrap_or_default();
            assert!(page.starts_with(&format!("yog {word}")), "{word}: {page}");
        }
    }
    // Asked from the top, though, yog does have a page for the three a human
    // types — what the namespace is, and that its own `--help` is the tool's.
    for word in ["gesture", "litany", "bl", "bz"] {
        assert!(answer(&argv(&["yog", "help", word])).is_some(), "{word}");
    }
}

/// Not a help ask: no argv at all, a bare GUI launch, the `$EDITOR` shim, a
/// command run for real, and a word with no page.
#[test]
fn anything_that_is_not_a_help_ask_is_left_alone() {
    assert_eq!(answer(&[]), None);
    assert_eq!(answer(&argv(&["yog"])), None);
    assert_eq!(answer(&argv(&["yog", "--editor-apply", "/co"])), None);
    assert_eq!(answer(&argv(&["yog", "env"])), None);
    assert_eq!(answer(&argv(&["yog", "exec", "bash"])), None);
    assert_eq!(answer(&argv(&["yog", "something-else", "--help"])), None);
    assert_eq!(answer(&argv(&["yog", "something-else"])), None);
}

/// An unknown word after the top-level flag is not an error page: the roster
/// is the honest answer to "what is there?".
#[test]
fn help_about_an_unknown_command_falls_back_to_the_roster() {
    let page = answer(&argv(&["yog", "--help", "enhance"])).unwrap_or_default();
    assert!(page.contains("Commands:"), "{page}");
}

/// The table is the single source, so no page can name a word that does not
/// run: each row's usage line opens with the very verb its dispatcher routes
/// on, and every row carries a paragraph to print.
#[test]
fn every_page_opens_with_the_word_its_dispatcher_routes_on() {
    for row in COMMANDS {
        assert!(
            row.usage.starts_with(&format!("yog {}", row.verb)),
            "{}: {}",
            row.verb,
            row.usage
        );
        assert!(!row.detail.is_empty(), "{} has no page", row.verb);
    }
}

/// Exactly one row is answerable-but-unadvertised, and it is the machine seam
/// — the same rule the two balls plugin binaries live under. Everything else
/// on the roster is a word a human types.
#[test]
fn the_only_unlisted_command_is_the_machine_seam() {
    let unlisted: Vec<&str> = COMMANDS
        .iter()
        .filter(|row| row.summary.is_empty())
        .map(|row| row.verb)
        .collect();
    assert_eq!(unlisted, vec![crate::control::SUBCMD]);
}

/// **The mint page states who provisions** (bl-6e0c). It used to be two pages
/// — this one and the retired `serve` verb's (bl-7942) — and the beat existed
/// because they had drifted: `serve`'s said the listener was up *"only where an
/// operator has provisioned certificates … and silently absent otherwise"* long
/// after bl-ae05 moved the trigger into the engine's own boot
/// ([`ensure`](crate::wire::provision::ensure), aimed at
/// [`LOOPBACK`](crate::wire::provision::LOOPBACK)). With one page the drift has
/// nowhere to happen, and what is still worth holding is that the page states
/// the boot mint and its aim, and names the explicit act as the const its
/// dispatcher routes on — so a rename cannot leave it naming a word that no
/// longer runs.
#[test]
fn the_mint_page_states_the_boot_mint_and_its_own_word() {
    let mint = crate::wire::provision::verb::SUBCMD;
    let text = answer(&argv(&["yog", mint, "--help"])).unwrap_or_default();
    assert!(text.contains("boot"), "the boot mint is unstated: {text}");
    assert!(text.contains("loopback"), "its aim is unstated: {text}");
    assert!(text.contains(mint), "the explicit act is unnamed: {text}");
    assert!(
        !text.contains("silently"),
        "the retired claim — a listener absent without a word — is gone"
    );
}

/// **Every environment reading the verb takes is on its page** (bl-cbcb).
/// `WIRE_FOOT` was not, and it is the only way to mint the foot-grade leaf a
/// `thrall` will open at all — so the two surfaces an operator meets while
/// provisioning a second box both stopped one word short of the act, and the
/// one place the word WAS printed is a line the founding mint says once in a
/// directory's life. Read off `READS` rather than spelled here, so a reading
/// added tomorrow reddens this instead of going undocumented.
#[test]
fn the_mint_page_names_every_setting_it_reads() {
    let mint = crate::wire::provision::verb::SUBCMD;
    let text = answer(&argv(&["yog", mint, "--help"])).unwrap_or_default();
    for reading in crate::wire::provision::verb::READS {
        assert!(text.contains(reading), "{reading} is undocumented: {text}");
    }
    // And the half a mint cannot perform: a leaf is issued into no workspace,
    // so the page names the act that seats it (bl-6b14).
    assert!(text.contains("/enroll"), "the enrolment is unnamed: {text}");
}

/// The probe is recognized only when the whole argv *is* the flag (§8.5's
/// "the flag form counts only when the tail is exactly the flag"), so no
/// foreign crate's option grammar has to be restated to be sure a token is not
/// somebody's value.
#[test]
fn a_discovery_probe_is_the_whole_argv_or_it_is_not_one() {
    for flag in ["--help", "-h", "--version", "-V", "--skill"] {
        assert!(is_discovery(&argv(&[flag])), "{flag}");
    }
    for not in [
        vec![],
        vec!["list"],
        vec!["--system", "--help"],
        vec!["--help", "close"],
        vec!["--", "--help"],
        vec!["--helpful"],
    ] {
        assert!(!is_discovery(&argv(&not)), "{not:?}");
    }
}