Skip to content

fix: return unhealthy exit statuses for diagnostic commands - #104

Merged
francoischalifour merged 3 commits into
mainfrom
fc/diagnostic-exit-status
Sep 3, 2026
Merged

fix: return unhealthy exit statuses for diagnostic commands#104
francoischalifour merged 3 commits into
mainfrom
fc/diagnostic-exit-status

Conversation

@francoischalifour

Copy link
Copy Markdown
Member

Why

altertable doctor and altertable profile status are diagnostic commands: they complete successfully as command executions even when the system they inspect is unhealthy. Previously, both commands rendered a complete report but exited with status 0.

That made the CLI hard to use safely from scripts, CI, and agents. Consumers had to parse report JSON—such as the healthy field from doctor—instead of relying on the conventional process exit status. At the same time, converting unhealthy reports into thrown CLI errors would have been a regression: it would discard the useful report from stdout and replace it with a stderr error envelope.

This PR makes diagnostic health visible through exit status while preserving the report as the command’s primary output.

What changed

Completed commands can return an exit status

The command execution contract now supports an optional { exitCode } result from a successfully completed command handler.

The command parser returns that result as part of its execution result, and the CLI bootstrap assigns it to process.exitCode after command output and update-notice handling complete. This keeps status handling centralized and avoids individual commands calling process.exit().

Thrown errors retain the existing error-rendering and stable exit-code behavior.

doctor reports health through its exit status

altertable doctor now:

  • exits 0 when the report is healthy;
  • exits 1 when one or more checks fail;
  • keeps warning-only reports successful;
  • preserves the full human, --json, or --agent report on stdout;
  • does not throw after reporting or emit a JSON error envelope on stderr for an unhealthy completed diagnostic.

Per-check details, remediation, HTTP status, and the aggregate report shape remain unchanged.

profile status follows the same diagnostic convention

altertable profile status now exits:

  • 0 when at least one credential plane is configured and every configured plane verifies successfully;
  • 1 when no credential planes are configured;
  • 1 when any configured credential verification fails.

The command still renders its profile and verification report to stdout in human, JSON, and agent modes. A failed verification is therefore observable both in the report body and through the process status, without being converted into a command-error envelope.

profile show remains observational and becomes more actionable

altertable profile show continues to exit 0 after a successful read, including for empty or partial profiles.

For the existing empty and partial profile states, it now provides:

  • human output with a Next steps: section;
  • structured JSON/agent output with next_steps, currently directing users to altertable profile configure.

Configured profiles include an empty next_steps array, giving structured consumers a stable field to inspect.

Documentation and release notes

The README now documents:

  • the different stdout/stderr contract for command errors versus unhealthy completed health checks;
  • doctor and profile status exit-status behavior;
  • the profile show next_steps field;
  • exit code 1 as the aggregate unhealthy-check result.

The unreleased changelog records the behavior change.

Design decisions

  • Exit code 1 is used as the aggregate unhealthy-diagnostic status. Detailed causes remain in the report rather than introducing a new per-diagnostic exit-code taxonomy.
  • Warning-only doctor reports remain successful because healthy is defined by the absence of failed checks.
  • Reports remain on stdout for all output modes. An unhealthy report is a completed diagnostic result, not an invocation failure.

Let completed commands return an explicit process status so health checks can preserve their full stdout reports without throwing or emitting error envelopes.

Make doctor and profile status return 1 for unhealthy results across human, JSON, and agent output. Keep profile show observational while adding setup guidance and structured next steps for empty or partial profiles.

@albert20260301 albert20260301 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Required before merge:

  1. Rename this PR with a Conventional Commit prefix (for example, fix(cli): return unhealthy diagnostic exit statuses) so the semantic-title workflow can pass.
  2. Investigate and fix the failing Canonical verification / Repository and integration job. It stops in Verify repository and integration paths before downstream build jobs run; GitHub has not exposed a more specific annotation beyond the failing command, so please rerun after the fix to capture the underlying test output if needed.

The diagnostic contract and regression coverage are otherwise well scoped.

@francoischalifour francoischalifour changed the title Return unhealthy exit statuses for diagnostic commands fix: return unhealthy exit statuses for diagnostic commands Sep 3, 2026
@francoischalifour
francoischalifour enabled auto-merge (squash) September 3, 2026 14:08
@francoischalifour
francoischalifour merged commit 96a8474 into main Sep 3, 2026
12 checks passed
@francoischalifour
francoischalifour deleted the fc/diagnostic-exit-status branch September 3, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants