Skip to content

app: wire distinct exit codes 5 (mode-conflict) and 6 (not-initialized) #111

@crowdy

Description

@crowdy

Background

Spec §5 at `docs/superpowers/specs/2026-04-21-no-proxy-mode-design.md` allocates:

code meaning
5 mode-conflict (`ErrModeConflict`)
6 not-initialized (`ErrNoMarker` reached by a command that requires the app to exist on the server)

Currently every error returned from a cobra RunE surfaces as exit code 1. `ErrModeConflict` is `%w`-wrapped through `formatModeConflictError` and `errors.Is(err, ErrModeConflict)` already works in-process — it just isn't plumbed to `os.Exit`.

Proposal

Plumb the exit code via the `cmd/cmdutil` entry point. Options:

  1. Inspect the final error via `errors.Is` at the top-level `rootCmd.Execute()` wrapper and call `os.Exit(5)` or `os.Exit(6)` accordingly.
  2. Add a typed error wrapper carrying the desired exit code and have `cmdutil` unwrap it.

Option 2 scales if more codes are added (it also lets us distinguish 4 = validation from 2 = usage).

Acceptance

  • `conoha app deploy --no-proxy ` against a proxy-marker app exits 5.
  • `conoha app logs ` against an unmarked server exits 6.
  • Existing exit 1 behavior preserved for generic errors.
  • Integration test in `cmd/app/` asserts the top-level `os.Exit` code.

Pointer

  • `cmd/cmdutil` — top-level Execute wrapper
  • `cmd/app/mode.go` — `ErrModeConflict`, `ErrNoMarker`
  • Spec §5 and plan Self-Review note at `docs/superpowers/plans/2026-04-21-no-proxy-mode.md`

Deferred during PR #103.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions