fix(doctor): lead with a verdict and next step; drop the stale checkpoint (U7)

A fresh-home `codewhale doctor` printed ~200 lines, an "update checkpoint
0.9.4" row for an install that had never been set up, and ended with "All
checks complete!" whatever it found.

- The first line under the header, and the last line, is now one verdict
  from the setup lane's own readiness: "Ready: setup is complete.", "Not
  ready: no model provider connected → run /provider in Codewhale, or
  `codewhale setup`.", or "Not ready: first-run setup is unfinished → run
  `codewhale setup`." Doctor still never probes credential values to decide.
- The update-checkpoint row prints only once first-run setup is complete; on
  a fresh home there is nothing to update.

Not in this slice (addendum U7 remainder): collapsing undeclared provider
rows into one line, and starting `codewhale setup` with provider readiness;
the setup help text lives in crates/cli (Honesty lane).

No-Issue: 0.10.1 addendum U7 (UX-6)

Checks (targeted, local, shared dirty tree):
- cargo test -p codewhale-tui --lib -- a_fresh_home_is_not_ready: 1 passed, 0 failed
- cargo test -p codewhale-tui --lib -- doctor (within the 448-test touched-module run): 0 failed

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
CodeWhale BotandClaude Opus 5.5 committed 2026-09-22 18:41:12 -07:00
1 parent 735fb509a8
commit 05ff7c7533
1 file changed
+41 -10
+41 -10
View File
@@ -4499,6 +4499,10 @@ async fn run_doctor(
.bold()
);
println!("{}", "==================".truecolor(sky_r, sky_g, sky_b));
// Verdict first (U7): the answer and the next step, before the detail.
let (verdict_state, _) = doctor_setup_state(config, workspace);
let verdict = doctor_verdict(&verdict_state);
println!("{}", verdict.truecolor(aqua_r, aqua_g, aqua_b).bold());
println!();
// Version info
@@ -5444,12 +5448,35 @@ async fn run_doctor(
}
println!();
println!(
"{}",
"All checks complete!"
.truecolor(aqua_r, aqua_g, aqua_b)
.bold()
println!("{}", verdict.truecolor(aqua_r, aqua_g, aqua_b).bold());
}
/// Doctor's one-line answer: ready, or the single next step (U7). Readiness
/// is the setup lane's own verdict; doctor never probes credential values to
/// decide it.
fn doctor_verdict(state: &codewhale_config::SetupState) -> &'static str {
if state.first_run_ready() {
return "Ready: setup is complete.";
}
let provider_ready = matches!(
state.status(codewhale_config::SetupStep::ProviderModel),
codewhale_config::StepStatus::Verified | codewhale_config::StepStatus::NeedsAction
);
if provider_ready {
"Not ready: first-run setup is unfinished → run `codewhale setup`."
} else {
"Not ready: no model provider connected → run /provider in Codewhale, or `codewhale setup`."
}
}
#[cfg(test)]
mod doctor_verdict_tests {
#[test]
fn a_fresh_home_is_not_ready_and_names_the_provider_step() {
let verdict = super::doctor_verdict(&codewhale_config::SetupState::default());
assert!(verdict.starts_with("Not ready"), "{verdict}");
assert!(verdict.contains("/provider"), "{verdict}");
}
}
const DOCTOR_LEGACY_STATE_ITEMS: &[&str] = &[
@@ -6159,11 +6186,15 @@ fn print_doctor_setup_report(
" {first_run_icon} first-run: {}",
doctor_ready_label(first_run_ready)
);
println!(
" {update_icon} update checkpoint {}: {}",
crate::tui::setup::CONSTITUTION_CHECKPOINT_VERSION,
doctor_ready_label(update_ready)
);
// An update checkpoint only means something once a prior setup exists;
// on a fresh home it is a stale version number with nothing to update.
if first_run_ready {
println!(
" {update_icon} update checkpoint {}: {}",
crate::tui::setup::CONSTITUTION_CHECKPOINT_VERSION,
doctor_ready_label(update_ready)
);
}
println!(
" {operate_icon} operate/fleet: {}",
doctor_ready_label(operate_ready)