mod ask;
mod choice;
mod common;
mod exists;
mod noul;
mod route;
mod score;
mod verify_decision;
use anyhow::Result;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(
long_about = "TypeSafe Jev typed judgments (choice, score, yes/no).\n\nJev is a \
separate typed-judgment API, not a chat model, so most jev subcommands do **not** accept \
the AI backend flags (`--ai-backend`, `--model`, `--claude-cli-*`, ...) — passing any \
of them is a clap error on those leaves. `route`, `exists` and `verify-decision` are the three \
exceptions to `-C/--repo`, and `verify-decision` is the one subcommand that also accepts \
the AI backend flags, since it uses an AI backend to split a decision comment into \
statements before checking them with Jev. An exported `OMNI_DEV_MODEL` is silently ignored \
by every Jev call. Use `--jev-model` on each subcommand instead to override the Jev model."
)]
pub struct JevCommand {
#[command(subcommand)]
pub command: JevSubcommands,
}
#[derive(Subcommand)]
pub enum JevSubcommands {
Choice(choice::ChoiceCommand),
Score(score::ScoreCommand),
Noul(noul::NoulCommand),
Ask(ask::AskCommand),
Route(route::RouteCommand),
Exists(exists::ExistsCommand),
VerifyDecision(verify_decision::VerifyDecisionCommand),
}
impl JevCommand {
pub async fn execute(self) -> Result<()> {
match self.command {
JevSubcommands::Choice(cmd) => cmd.execute().await,
JevSubcommands::Score(cmd) => cmd.execute().await,
JevSubcommands::Noul(cmd) => cmd.execute().await,
JevSubcommands::Ask(cmd) => cmd.execute().await,
JevSubcommands::Route(cmd) => cmd.execute().await,
JevSubcommands::Exists(cmd) => cmd.execute().await,
JevSubcommands::VerifyDecision(cmd) => cmd.execute().await,
}
}
}
#[cfg(feature = "mcp")]
pub(crate) use common::{format_output_with_cache, JevFormat};
#[cfg(feature = "mcp")]
pub(crate) use route::{build_ladders, fetch_docs};
#[cfg(feature = "mcp")]
pub(crate) use verify_decision::fetch_input;
#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[tokio::test]
async fn exists_runs_through_the_group_dispatch() {
let dir = crate::test_support::git_repo::commit_files(&[("walk.rs", b"fn caller() {}\n")]);
let issue = dir.path().join("issue.txt");
std::fs::write(&issue, "Reuse `caller`.").unwrap();
let command = JevCommand::try_parse_from([
"jev",
"exists",
"--issue-file",
issue.to_str().unwrap(),
"-C",
dir.path().to_str().unwrap(),
"--dry-run",
])
.unwrap();
command.execute().await.unwrap();
}
}