use std::path::Path;
use speccoder_core::{CommandResult, CommandStatus};
#[must_use]
pub fn change(
path: &Path,
request: &str,
checks: &[String],
run: bool,
via: speccoder_core::actions::Via,
options: &crate::RunOptions,
asked: Option<(&str, &Path)>,
) -> CommandResult {
let format = crate::format::at(path);
let Some(root) = format.detect(path) else {
return CommandResult::new(
"do",
CommandStatus::NotAProject,
&(format.messages().not_a_project)(path),
)
.with_code("NO-PROJECT");
};
let rec = match format.record_change(&root, request, checks) {
Ok(r) => r,
Err(e) => {
return CommandResult::new("do", CommandStatus::UsageError, &e).with_code("USAGE");
}
};
let approved = crate::review::decide(
&root,
Some(&rec.feature),
std::slice::from_ref(&rec.requirement),
"approve",
None,
via,
);
if approved.status() != CommandStatus::Ok {
return CommandResult::carried("do", &approved);
}
if let Some((conversation, state)) = asked {
let _ = crate::ladder::record_origin(
&crate::worktree::project_state_dir(state, &root),
&speccoder_core::ladder::subject(&rec.feature, &rec.requirement),
vec![speccoder_core::ladder::asked(
conversation,
crate::bug::confirm::now(),
)],
);
}
let files = crate::hosting::uncommitted(&root, Some(&rec.feature));
if !files.is_empty() {
let committed = crate::hosting::commit_planning_as(
&root,
Some(&rec.feature),
&files,
Some(&format!("quick change: {}", rec.title)),
);
if committed.status() != CommandStatus::Ok {
return CommandResult::carried("do", &committed);
}
}
let said = format!(
"recorded \"{}\" as {} and {} in {}",
rec.title, rec.requirement, rec.task, rec.feature
);
if !run {
return CommandResult::ok(
"do",
&format!(
"{said}; run it: speccoder run --feature {} --task {}",
rec.feature, rec.task
),
)
.with_next(vec![speccoder_core::next::NextStep {
command: format!(
"speccoder run --feature {} --task {}",
rec.feature, rec.task
),
why: "the change, judged on evidence".to_owned(),
}]);
}
let result = crate::run(&root, Some(&rec.feature), &rec.task, options);
let status = result.status();
let message = format!("{said}; {}", result.message());
result.reworded(status, &message)
}