use crate::app::{App, DiffSource};
pub(super) fn handle_unblind(app: &mut App) {
if !app.blind_mode {
app.set_message("Blind-tests mode already off");
return;
}
app.blind_mode = false;
if matches!(app.diff_source, DiffSource::Remote { .. }) {
match app.refresh_remote() {
Ok(()) => app.set_message(format!(
"Blind-tests off: restored {} file(s)",
app.diff_files.len()
)),
Err(e) => app.set_error(format!("Unblind refresh failed: {e}")),
}
} else {
match app.reload_diff_files() {
Ok(n) => app.set_message(format!("Blind-tests off: restored {n} file(s)")),
Err(e) => app.set_error(format!("Unblind reload failed: {e}")),
}
}
}
pub(super) fn handle_blind(app: &mut App) {
if app.blind_mode {
app.set_message("Blind-tests mode already on");
} else if app.blind_patterns.is_empty() {
app.set_warning(
":blind is a no-op (hidden_from_reviewer empty in .travelagent/review.toml)",
);
} else {
app.blind_mode = true;
let hidden = app.apply_blind_filter();
app.set_message(format!("Blind-tests on: hiding {hidden} file(s)"));
}
}
pub(super) fn handle_reload_review_config(app: &mut App) {
let root = app.vcs_info.root_path.clone();
if !root.is_absolute() {
app.set_warning(
":reload-review-config has no effect without a repo root (demo / remote-only mode)",
);
return;
}
match travelagent_core::review_config::load_review_config(&root) {
Ok(outcome) => {
for w in &outcome.warnings {
app.set_warning(w.clone());
}
app.blind_patterns = outcome.config.hidden_from_reviewer;
if app.blind_mode {
let refreshed = if matches!(app.diff_source, DiffSource::Remote { .. }) {
app.refresh_remote().map_err(|e| format!("{e}"))
} else {
app.reload_diff_files()
.map(|_| ())
.map_err(|e| format!("{e}"))
};
match refreshed {
Ok(()) => {
let hidden = app.apply_blind_filter();
app.set_message(format!("review.toml reloaded; hiding {hidden} file(s)"));
}
Err(e) => {
app.set_error(format!(
"Reload failed (patterns updated, diff refresh error): {e}"
));
}
}
} else {
app.set_message(format!(
"review.toml reloaded; {} pattern(s) staged (run :blind to apply)",
app.blind_patterns.len()
));
}
}
Err(e) => {
app.set_error(format!("Failed to reload .travelagent/review.toml: {e}"));
}
}
}
pub(super) fn handle_spar(app: &mut App) {
if app.spar_mode {
app.set_message("Sparring Review mode already on");
return;
}
match crate::enter_spar_mode(app) {
Ok(crate::SparEntryOutcome::Created(branch)) => {
app.spar_mode = true;
app.set_message(format!("Sparring mode on: created branch {branch}"));
}
Ok(crate::SparEntryOutcome::Resumed(branch)) => {
app.spar_mode = true;
app.set_message(format!("Sparring mode on: resumed branch {branch}"));
}
Ok(crate::SparEntryOutcome::FlagOnly(reason)) => {
app.spar_mode = true;
app.set_warning(format!(
"Sparring mode flag-only — {}",
reason.user_message()
));
}
Err(e) => {
app.set_error(format!("Could not enter sparring mode: {e}"));
}
}
}
pub(super) fn handle_unspar(app: &mut App) {
if !app.spar_mode {
app.set_message("Sparring Review mode already off");
} else {
app.spar_mode = false;
app.set_message("Sparring Review mode off");
}
}
pub(super) fn handle_spec(app: &mut App) {
if !app.spar_mode {
app.set_warning(":spec requires Sparring Review mode (use --spar or :spar first)");
} else {
use travelagent_core::model::CommentType;
app.comment.comment_type = CommentType::Spec;
app.set_message("Next comment will be a Spec; use :specs to list existing ones");
}
}
pub(super) fn handle_specs(app: &mut App) {
let n = app.engine.session().spec_count();
if n == 0 {
app.set_message("No specs yet — use :spec then add a comment (requires :spar)");
} else {
app.set_message(format!(
"{n} spec{} on this session (see `trv_list_spec_comments` for detail)",
if n == 1 { "" } else { "s" }
));
}
}