refactor(doctor): extract section banner + fail-and-issue helpers (#27830)

`hermes_cli/doctor.py` had two recurring patterns:

1. **15 section headers** of the form `print() ; print(color("◆ Name", Colors.CYAN, Colors.BOLD))`
   bracketed by 3-line `# =====` / `# Check: X` / `# =====` comment banners.

2. **Paired `check_fail(...) ; issues.append(...)`** for every diagnostic that emits both a
   user-visible failure and an auto-fix instruction.

Add two helpers and collapse the patterns:

  def _section(title):
      print()
      print(color(f"◆ {title}", Colors.CYAN, Colors.BOLD))

  def _fail_and_issue(text, detail, fix, issues):
      check_fail(text, detail)
      issues.append(fix)

Replacements:
- 15 `# =====/# X/# =====` banner triples + section header pairs compressed to `_section(...)`
- All 18 `check_fail + issues.append` pairs collapsed to `_fail_and_issue(...)` (single-line
  where the call fits under 120 chars, multi-line where it doesn't)
- Net -5 LOC (`+128 / -133`)

The LOC delta is modest after wrapping long calls onto multi-line form for readability — the
real win is uniform call shape and removal of two parallel-pattern footguns. There is now
exactly one way to emit a diagnostic that pairs a user-visible failure with a fix instruction.

Behavior is byte-identical. `_section` produces the same blank line + bold-cyan output the
inline two prints did, and `_fail_and_issue` does the same `check_fail + issues.append`
sequence in the same order. Verified empirically by diffing live `run_doctor()` stdout from
this branch against `origin/main` — `diff -q` reports zero differences.

Test plan:
- All 69 tests across test_doctor.py, test_doctor_command_install.py, and
  test_doctor_dedicated_provider_skip.py pass
- `ruff check hermes_cli/doctor.py` clean
- Live `run_doctor()` output byte-identical to origin/main

Refs #23972 (Phase 2 tracker — dedup-only refactor in line with the "net-LOC-negative"
discipline).
This commit is contained in:
kshitij
2026-05-18 00:45:25 -07:00
committed by GitHub
parent 94c523f0c5
commit 41f1eddee3

View File

@@ -195,6 +195,18 @@ def check_info(text: str):
print(f" {color('', Colors.CYAN)} {text}") print(f" {color('', Colors.CYAN)} {text}")
def _section(title: str) -> None:
"""Print a doctor section banner: blank line + bold cyan ◆ title."""
print()
print(color(f"{title}", Colors.CYAN, Colors.BOLD))
def _fail_and_issue(text: str, detail: str, fix: str, issues: list[str]) -> None:
"""Emit a check_fail and append the corresponding fix instruction."""
check_fail(text, detail)
issues.append(fix)
def _check_gateway_service_linger(issues: list[str]) -> None: def _check_gateway_service_linger(issues: list[str]) -> None:
"""Warn when a systemd user gateway service will stop after logout.""" """Warn when a systemd user gateway service will stop after logout."""
try: try:
@@ -214,9 +226,7 @@ def _check_gateway_service_linger(issues: list[str]) -> None:
if not unit_path.exists(): if not unit_path.exists():
return return
print() _section("Gateway Service")
print(color("◆ Gateway Service", Colors.CYAN, Colors.BOLD))
linger_enabled, linger_detail = get_systemd_linger_status() linger_enabled, linger_detail = get_systemd_linger_status()
if linger_enabled is True: if linger_enabled is True:
check_ok("Systemd linger enabled", "(gateway service survives logout)") check_ok("Systemd linger enabled", "(gateway service survives logout)")
@@ -373,11 +383,7 @@ def run_doctor(args):
print(color("│ 🩺 Hermes Doctor │", Colors.CYAN)) print(color("│ 🩺 Hermes Doctor │", Colors.CYAN))
print(color("└─────────────────────────────────────────────────────────┘", Colors.CYAN)) print(color("└─────────────────────────────────────────────────────────┘", Colors.CYAN))
# ========================================================================= _section("Security Advisories")
# Check: Security advisories (RUNS FIRST — these are the most urgent)
# =========================================================================
print()
print(color("◆ Security Advisories", Colors.CYAN, Colors.BOLD))
try: try:
from hermes_cli.security_advisories import ( from hermes_cli.security_advisories import (
detect_compromised, detect_compromised,
@@ -423,12 +429,7 @@ def run_doctor(args):
# Never let a bug in the advisory check block the rest of doctor. # Never let a bug in the advisory check block the rest of doctor.
check_warn(f"Security advisory check failed: {e}") check_warn(f"Security advisory check failed: {e}")
# ========================================================================= _section("Python Environment")
# Check: Python version
# =========================================================================
print()
print(color("◆ Python Environment", Colors.CYAN, Colors.BOLD))
py_version = sys.version_info py_version = sys.version_info
if py_version >= (3, 11): if py_version >= (3, 11):
check_ok(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}") check_ok(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}")
@@ -438,8 +439,12 @@ def run_doctor(args):
elif py_version >= (3, 8): elif py_version >= (3, 8):
check_warn(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}", "(3.10+ recommended)") check_warn(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}", "(3.10+ recommended)")
else: else:
check_fail(f"Python {py_version.major}.{py_version.minor}.{py_version.micro}", "(3.10+ required)") _fail_and_issue(
issues.append("Upgrade Python to 3.10+") f"Python {py_version.major}.{py_version.minor}.{py_version.micro}",
"(3.10+ required)",
"Upgrade Python to 3.10+",
issues,
)
# Check if in virtual environment # Check if in virtual environment
in_venv = sys.prefix != sys.base_prefix in_venv = sys.prefix != sys.base_prefix
@@ -448,12 +453,7 @@ def run_doctor(args):
else: else:
check_warn("Not in virtual environment", "(recommended)") check_warn("Not in virtual environment", "(recommended)")
# ========================================================================= _section("Required Packages")
# Check: Required packages
# =========================================================================
print()
print(color("◆ Required Packages", Colors.CYAN, Colors.BOLD))
required_packages = [ required_packages = [
("openai", "OpenAI SDK"), ("openai", "OpenAI SDK"),
("rich", "Rich (terminal UI)"), ("rich", "Rich (terminal UI)"),
@@ -473,8 +473,7 @@ def run_doctor(args):
__import__(module) __import__(module)
check_ok(name) check_ok(name)
except ImportError: except ImportError:
check_fail(name, "(missing)") _fail_and_issue(name, "(missing)", f"Install {name}: {_python_install_cmd()} {module}", issues)
issues.append(f"Install {name}: {_python_install_cmd()} {module}")
for module, name in optional_packages: for module, name in optional_packages:
try: try:
@@ -483,12 +482,7 @@ def run_doctor(args):
except ImportError: except ImportError:
check_warn(name, "(optional, not installed)") check_warn(name, "(optional, not installed)")
# ========================================================================= _section("Configuration Files")
# Check: Configuration files
# =========================================================================
print()
print(color("◆ Configuration Files", Colors.CYAN, Colors.BOLD))
# Check ~/.hermes/.env (primary location for user config) # Check ~/.hermes/.env (primary location for user config)
env_path = HERMES_HOME / '.env' env_path = HERMES_HOME / '.env'
if env_path.exists(): if env_path.exists():
@@ -611,14 +605,15 @@ def run_doctor(args):
and not (provider_ids_to_accept & valid_provider_ids) and not (provider_ids_to_accept & valid_provider_ids)
): ):
known_list = ", ".join(sorted(known_providers)) if known_providers else "(unavailable)" known_list = ", ".join(sorted(known_providers)) if known_providers else "(unavailable)"
check_fail( _fail_and_issue(
f"model.provider '{provider_raw}' is not a recognised provider", f"model.provider '{provider_raw}' is not a recognised provider",
f"(known: {known_list})", f"(known: {known_list})",
) (
issues.append( f"model.provider '{provider_raw}' is unknown. "
f"model.provider '{provider_raw}' is unknown. " f"Valid providers: {known_list}. "
f"Valid providers: {known_list}. " f"Fix: run 'hermes config set model.provider <valid_provider>'"
f"Fix: run 'hermes config set model.provider <valid_provider>'" ),
issues,
) )
# Warn if model is set to a provider-prefixed name on a provider that doesn't use them # Warn if model is set to a provider-prefixed name on a provider that doesn't use them
@@ -677,14 +672,15 @@ def run_doctor(args):
or status.get("api_key") or status.get("api_key")
) )
if not configured: if not configured:
check_fail( _fail_and_issue(
f"model.provider '{runtime_provider}' is set but no API key is configured", f"model.provider '{runtime_provider}' is set but no API key is configured",
"(check ~/.hermes/.env or run 'hermes setup')", "(check ~/.hermes/.env or run 'hermes setup')",
) (
issues.append( f"No credentials found for provider '{runtime_provider}'. "
f"No credentials found for provider '{runtime_provider}'. " f"Run 'hermes setup' or set the provider's API key in {_DHH}/.env, "
f"Run 'hermes setup' or set the provider's API key in {_DHH}/.env, " f"or switch providers with 'hermes config set model.provider <name>'"
f"or switch providers with 'hermes config set model.provider <name>'" ),
issues,
) )
except Exception: except Exception:
pass pass
@@ -768,8 +764,7 @@ def run_doctor(args):
from hermes_cli.config import validate_config_structure from hermes_cli.config import validate_config_structure
config_issues = validate_config_structure() config_issues = validate_config_structure()
if config_issues: if config_issues:
print() _section("Config Structure")
print(color("◆ Config Structure", Colors.CYAN, Colors.BOLD))
for ci in config_issues: for ci in config_issues:
if ci.severity == "error": if ci.severity == "error":
check_fail(ci.message) check_fail(ci.message)
@@ -782,12 +777,7 @@ def run_doctor(args):
except Exception: except Exception:
pass pass
# ========================================================================= _section("Auth Providers")
# Check: Auth providers
# =========================================================================
print()
print(color("◆ Auth Providers", Colors.CYAN, Colors.BOLD))
try: try:
from hermes_cli.auth import ( from hermes_cli.auth import (
get_nous_auth_status, get_nous_auth_status,
@@ -859,12 +849,7 @@ def run_doctor(args):
"(optional — only required to import tokens from an existing Codex CLI login)" "(optional — only required to import tokens from an existing Codex CLI login)"
) )
# ========================================================================= _section("Directory Structure")
# Check: Directory structure
# =========================================================================
print()
print(color("◆ Directory Structure", Colors.CYAN, Colors.BOLD))
hermes_home = HERMES_HOME hermes_home = HERMES_HOME
if hermes_home.exists(): if hermes_home.exists():
check_ok(f"{_DHH} directory exists") check_ok(f"{_DHH} directory exists")
@@ -976,13 +961,8 @@ def run_doctor(args):
_check_gateway_service_linger(issues) _check_gateway_service_linger(issues)
# =========================================================================
# Check: Command installation (hermes bin symlink)
# =========================================================================
if sys.platform != "win32": if sys.platform != "win32":
print() _section("Command Installation")
print(color("◆ Command Installation", Colors.CYAN, Colors.BOLD))
# Determine the venv entry point location # Determine the venv entry point location
_venv_bin = None _venv_bin = None
for _venv_name in ("venv", ".venv"): for _venv_name in ("venv", ".venv"):
@@ -1056,12 +1036,7 @@ def run_doctor(args):
else: else:
issues.append(f"Missing {_cmd_link_display}/hermes symlink — run 'hermes doctor --fix'") issues.append(f"Missing {_cmd_link_display}/hermes symlink — run 'hermes doctor --fix'")
# ========================================================================= _section("External Tools")
# Check: External tools
# =========================================================================
print()
print(color("◆ External Tools", Colors.CYAN, Colors.BOLD))
# Git # Git
if _safe_which("git"): if _safe_which("git"):
check_ok("git") check_ok("git")
@@ -1087,11 +1062,14 @@ def run_doctor(args):
if result is not None and result.returncode == 0: if result is not None and result.returncode == 0:
check_ok("docker", "(daemon running)") check_ok("docker", "(daemon running)")
else: else:
check_fail("docker daemon not running") _fail_and_issue("docker daemon not running", "", "Start Docker daemon", issues)
issues.append("Start Docker daemon")
else: else:
check_fail("docker not found", "(required for TERMINAL_ENV=docker)") _fail_and_issue(
issues.append("Install Docker or change TERMINAL_ENV") "docker not found",
"(required for TERMINAL_ENV=docker)",
"Install Docker or change TERMINAL_ENV",
issues,
)
elif _safe_which("docker"): elif _safe_which("docker"):
check_ok("docker", "(optional)") check_ok("docker", "(optional)")
elif _is_termux(): elif _is_termux():
@@ -1126,11 +1104,14 @@ def run_doctor(args):
if result is not None and result.returncode == 0: if result is not None and result.returncode == 0:
check_ok(f"SSH connection to {ssh_host}") check_ok(f"SSH connection to {ssh_host}")
else: else:
check_fail(f"SSH connection to {ssh_host}") _fail_and_issue(f"SSH connection to {ssh_host}", "", f"Check SSH configuration for {ssh_host}", issues)
issues.append(f"Check SSH configuration for {ssh_host}")
else: else:
check_fail("TERMINAL_SSH_HOST not set", "(required for TERMINAL_ENV=ssh)") _fail_and_issue(
issues.append("Set TERMINAL_SSH_HOST in .env") "TERMINAL_SSH_HOST not set",
"(required for TERMINAL_ENV=ssh)",
"Set TERMINAL_SSH_HOST in .env",
issues,
)
# Daytona (if using daytona backend) # Daytona (if using daytona backend)
if terminal_env == "daytona": if terminal_env == "daytona":
@@ -1138,14 +1119,22 @@ def run_doctor(args):
if daytona_key: if daytona_key:
check_ok("Daytona API key", "(configured)") check_ok("Daytona API key", "(configured)")
else: else:
check_fail("DAYTONA_API_KEY not set", "(required for TERMINAL_ENV=daytona)") _fail_and_issue(
issues.append("Set DAYTONA_API_KEY environment variable") "DAYTONA_API_KEY not set",
"(required for TERMINAL_ENV=daytona)",
"Set DAYTONA_API_KEY environment variable",
issues,
)
try: try:
from daytona import Daytona # noqa: F401 — SDK presence check from daytona import Daytona # noqa: F401 — SDK presence check
check_ok("daytona SDK", "(installed)") check_ok("daytona SDK", "(installed)")
except ImportError: except ImportError:
check_fail("daytona SDK not installed", "(pip install daytona)") _fail_and_issue(
issues.append("Install daytona SDK: pip install daytona") "daytona SDK not installed",
"(pip install daytona)",
"Install daytona SDK: pip install daytona",
issues,
)
# Vercel Sandbox (if using vercel_sandbox backend) # Vercel Sandbox (if using vercel_sandbox backend)
if terminal_env == "vercel_sandbox": if terminal_env == "vercel_sandbox":
@@ -1155,32 +1144,50 @@ def run_doctor(args):
check_ok("Vercel runtime", f"({runtime})") check_ok("Vercel runtime", f"({runtime})")
else: else:
supported = ", ".join(_SUPPORTED_VERCEL_RUNTIMES) supported = ", ".join(_SUPPORTED_VERCEL_RUNTIMES)
check_fail("Vercel runtime unsupported", f"({runtime}; use {supported})") _fail_and_issue(
issues.append(f"Set TERMINAL_VERCEL_RUNTIME to one of: {supported}") "Vercel runtime unsupported",
f"({runtime}; use {supported})",
f"Set TERMINAL_VERCEL_RUNTIME to one of: {supported}",
issues,
)
disk = os.getenv("TERMINAL_CONTAINER_DISK", "51200").strip() disk = os.getenv("TERMINAL_CONTAINER_DISK", "51200").strip()
if disk in {"", "0", "51200"}: if disk in {"", "0", "51200"}:
check_ok("Vercel disk setting", "(uses platform default)") check_ok("Vercel disk setting", "(uses platform default)")
else: else:
check_fail("Vercel custom disk unsupported", "(reset terminal.container_disk to 51200)") _fail_and_issue(
issues.append("Vercel Sandbox does not support custom container_disk; use the shared default 51200") "Vercel custom disk unsupported",
"(reset terminal.container_disk to 51200)",
"Vercel Sandbox does not support custom container_disk; use the shared default 51200",
issues,
)
if importlib.util.find_spec("vercel") is not None: if importlib.util.find_spec("vercel") is not None:
check_ok("vercel SDK", "(installed)") check_ok("vercel SDK", "(installed)")
else: else:
check_fail("vercel SDK not installed", "(pip install 'hermes-agent[vercel]')") _fail_and_issue(
issues.append("Install the Vercel optional dependency: pip install 'hermes-agent[vercel]'") "vercel SDK not installed",
"(pip install 'hermes-agent[vercel]')",
"Install the Vercel optional dependency: pip install 'hermes-agent[vercel]'",
issues,
)
auth_status = describe_vercel_auth() auth_status = describe_vercel_auth()
if auth_status.ok: if auth_status.ok:
check_ok("Vercel auth", f"({auth_status.label})") check_ok("Vercel auth", f"({auth_status.label})")
elif auth_status.label.startswith("partial"): elif auth_status.label.startswith("partial"):
check_fail("Vercel auth incomplete", f"({auth_status.label})") _fail_and_issue(
issues.append("Set VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID together") "Vercel auth incomplete",
f"({auth_status.label})",
"Set VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID together",
issues,
)
else: else:
check_fail("Vercel auth not configured", f"({auth_status.label})") _fail_and_issue(
issues.append( "Vercel auth not configured",
"Configure Vercel Sandbox auth with VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID" f"({auth_status.label})",
"Configure Vercel Sandbox auth with VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID",
issues,
) )
for line in auth_status.detail_lines: for line in auth_status.detail_lines:
check_info(f"Vercel auth {line}") check_info(f"Vercel auth {line}")
@@ -1320,12 +1327,7 @@ def run_doctor(args):
for note in _termux_install_all_fallback_notes(): for note in _termux_install_all_fallback_notes():
check_info(note) check_info(note)
# ========================================================================= _section("API Connectivity")
# Check: API connectivity
# =========================================================================
print()
print(color("◆ API Connectivity", Colors.CYAN, Colors.BOLD))
# Refactor: every connectivity probe below is HTTP-bound and fully # Refactor: every connectivity probe below is HTTP-bound and fully
# independent. Running them in series spent ~5s wall on a typical # independent. Running them in series spent ~5s wall on a typical
# workstation (2s of that was boto3's IMDS lookup for AWS credentials, # workstation (2s of that was boto3's IMDS lookup for AWS credentials,
@@ -1673,12 +1675,7 @@ def run_doctor(args):
for _issue in _issues_to_add: for _issue in _issues_to_add:
issues.append(_issue) issues.append(_issue)
# ========================================================================= _section("Tool Availability")
# Check: Tool Availability
# =========================================================================
print()
print(color("◆ Tool Availability", Colors.CYAN, Colors.BOLD))
try: try:
# Add project root to path for imports # Add project root to path for imports
sys.path.insert(0, str(PROJECT_ROOT)) sys.path.insert(0, str(PROJECT_ROOT))
@@ -1706,12 +1703,7 @@ def run_doctor(args):
except Exception as e: except Exception as e:
check_warn("Could not check tool availability", f"({e})") check_warn("Could not check tool availability", f"({e})")
# ========================================================================= _section("Skills Hub")
# Check: Skills Hub
# =========================================================================
print()
print(color("◆ Skills Hub", Colors.CYAN, Colors.BOLD))
hub_dir = HERMES_HOME / "skills" / ".hub" hub_dir = HERMES_HOME / "skills" / ".hub"
if hub_dir.exists(): if hub_dir.exists():
check_ok("Skills Hub directory exists") check_ok("Skills Hub directory exists")
@@ -1752,12 +1744,7 @@ def run_doctor(args):
else: else:
check_warn("No GITHUB_TOKEN", f"(60 req/hr rate limit — set in {_DHH}/.env for better rates)") check_warn("No GITHUB_TOKEN", f"(60 req/hr rate limit — set in {_DHH}/.env for better rates)")
# ========================================================================= _section("Memory Provider")
# Memory Provider (only check the active provider, if any)
# =========================================================================
print()
print(color("◆ Memory Provider", Colors.CYAN, Colors.BOLD))
_active_memory_provider = "" _active_memory_provider = ""
try: try:
import yaml as _yaml import yaml as _yaml
@@ -1782,8 +1769,12 @@ def run_doctor(args):
elif not hcfg.enabled: elif not hcfg.enabled:
check_info(f"Honcho disabled (set enabled: true in {_honcho_cfg_path} to activate)") check_info(f"Honcho disabled (set enabled: true in {_honcho_cfg_path} to activate)")
elif not (hcfg.api_key or hcfg.base_url): elif not (hcfg.api_key or hcfg.base_url):
check_fail("Honcho API key or base URL not set", "run: hermes memory setup") _fail_and_issue(
issues.append("No Honcho API key — run 'hermes memory setup'") "Honcho API key or base URL not set",
"run: hermes memory setup",
"No Honcho API key — run 'hermes memory setup'",
issues,
)
else: else:
from plugins.memory.honcho.client import get_honcho_client, reset_honcho_client from plugins.memory.honcho.client import get_honcho_client, reset_honcho_client
reset_honcho_client() reset_honcho_client()
@@ -1794,11 +1785,14 @@ def run_doctor(args):
f"workspace={hcfg.workspace_id} mode={hcfg.recall_mode} freq={hcfg.write_frequency}", f"workspace={hcfg.workspace_id} mode={hcfg.recall_mode} freq={hcfg.write_frequency}",
) )
except Exception as _e: except Exception as _e:
check_fail("Honcho connection failed", str(_e)) _fail_and_issue("Honcho connection failed", str(_e), f"Honcho unreachable: {_e}", issues)
issues.append(f"Honcho unreachable: {_e}")
except ImportError: except ImportError:
check_fail("honcho-ai not installed", "pip install honcho-ai") _fail_and_issue(
issues.append("Honcho is set as memory provider but honcho-ai is not installed") "honcho-ai not installed",
"pip install honcho-ai",
"Honcho is set as memory provider but honcho-ai is not installed",
issues,
)
except Exception as _e: except Exception as _e:
check_warn("Honcho check failed", str(_e)) check_warn("Honcho check failed", str(_e))
elif _active_memory_provider == "mem0": elif _active_memory_provider == "mem0":
@@ -1810,11 +1804,19 @@ def run_doctor(args):
check_ok("Mem0 API key configured") check_ok("Mem0 API key configured")
check_info(f"user_id={mem0_cfg.get('user_id', '?')} agent_id={mem0_cfg.get('agent_id', '?')}") check_info(f"user_id={mem0_cfg.get('user_id', '?')} agent_id={mem0_cfg.get('agent_id', '?')}")
else: else:
check_fail("Mem0 API key not set", "(set MEM0_API_KEY in .env or run hermes memory setup)") _fail_and_issue(
issues.append("Mem0 is set as memory provider but API key is missing") "Mem0 API key not set",
"(set MEM0_API_KEY in .env or run hermes memory setup)",
"Mem0 is set as memory provider but API key is missing",
issues,
)
except ImportError: except ImportError:
check_fail("Mem0 plugin not loadable", "pip install mem0ai") _fail_and_issue(
issues.append("Mem0 is set as memory provider but mem0ai is not installed") "Mem0 plugin not loadable",
"pip install mem0ai",
"Mem0 is set as memory provider but mem0ai is not installed",
issues,
)
except Exception as _e: except Exception as _e:
check_warn("Mem0 check failed", str(_e)) check_warn("Mem0 check failed", str(_e))
else: else:
@@ -1831,17 +1833,13 @@ def run_doctor(args):
except Exception as _e: except Exception as _e:
check_warn(f"{_active_memory_provider} check failed", str(_e)) check_warn(f"{_active_memory_provider} check failed", str(_e))
# =========================================================================
# Profiles
# =========================================================================
try: try:
from hermes_cli.profiles import list_profiles, _get_wrapper_dir, profile_exists from hermes_cli.profiles import list_profiles, _get_wrapper_dir, profile_exists
import re as _re import re as _re
named_profiles = [p for p in list_profiles() if not p.is_default] named_profiles = [p for p in list_profiles() if not p.is_default]
if named_profiles: if named_profiles:
print() _section("Profiles")
print(color("◆ Profiles", Colors.CYAN, Colors.BOLD))
check_ok(f"{len(named_profiles)} profile(s) found") check_ok(f"{len(named_profiles)} profile(s) found")
wrapper_dir = _get_wrapper_dir() wrapper_dir = _get_wrapper_dir()
for p in named_profiles: for p in named_profiles:
@@ -1878,9 +1876,6 @@ def run_doctor(args):
except Exception: except Exception:
pass pass
# =========================================================================
# Summary
# =========================================================================
print() print()
remaining_issues = issues + manual_issues remaining_issues = issues + manual_issues
if should_fix and fixed_count > 0: if should_fix and fixed_count > 0: