Skip to content

CLI consistency: uniform errors/usage, harmonized flags, universal progress bars#23

Merged
cornish merged 4 commits into
mainfrom
fix/cli-error-usage-consistency
Jun 30, 2026
Merged

CLI consistency: uniform errors/usage, harmonized flags, universal progress bars#23
cornish merged 4 commits into
mainfrom
fix/cli-error-usage-consistency

Conversation

@cornish

@cornish cornish commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

A pass over CLI consistency (breaking, pre-1.0). Four commits:

1. Consistent error/usage output (all commands)

  • Errors no longer double-printed (cobra's Error: silenced at root; main prints a single error: <msg>).
  • Usage menu shown uniformly on arg/flag errors (previously crop/downsample suppressed it), omitted on runtime errors. Exit codes unchanged.

2. extract --force/-f

  • Overwrite guard matching the other file-writing commands (previously extract silently overwrote).

3. Harmonized associated-edit flags (label/macro/overview/thumbnail × remove/replace)

  • Overwrite is -f/--force (was --overwrite, removed).
  • Aspect-guard bypass moved --force--allow-aspect-mismatch (no overloaded --force).
  • Removed the per-command -q/--quiet shadow; one global -q/--quiet that uniformly suppresses progress and success/info output.
  • Default output suffix <stem>_edited (was _relabeled).

4. Universal progress bars

  • Every write path now shows a tile-progress bar (was only downsample/crop/--factor): all convert targets, transcode, crop --lossless, --to bif.
  • Engine paths via a new retile.Spec.OnTileWritten hook; manual loops via direct counters.
  • Gated on --quiet AND stderr-is-a-TTY (no escape-codes into pipes/CI).

Test Plan

  • CI green (unit + integration + dciodvfy + IFE validator). New tests: error/usage behavior, progress hook/no-op, sumLevelTiles.

🤖 Generated with Claude Code

cornish and others added 4 commits June 29, 2026 22:07
Two inconsistencies in the cobra wiring:

1. Every command double-printed errors — cobra's "Error: <msg>" plus main()'s
   "error: <msg>". main() owns error output, so silence cobra's print once at
   the root (rootCmd.SilenceErrors = true). Removes the redundant line everywhere.

2. Usage-on-arg-error was inconsistent. Most commands set cmd.SilenceUsage inside
   RunE (so an arg/flag-parse error, which fails before RunE, still shows the
   usage menu), but crop and downsample set SilenceUsage:true in the struct,
   suppressing usage even for arg errors (no help shown). Move both to the RunE
   pattern so they match convert et al.

Result, uniform across all commands:
  - arg/flag error  -> usage menu + a single "error: <msg>"  (exit 1)
  - runtime error   -> a single "error: <msg>", no flag wall (exit 1)
validate's exit codes (0 ok / 1 operational / 2 validation-failed, report-only)
are unchanged; its now-redundant per-command SilenceErrors is dropped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
extract now refuses to overwrite an existing output unless --force is given
(fail-fast existence guard), matching convert/crop/downsample/region. Update
scripts/qa/run-matrix.sh extract calls to pass -f so the matrix stays
re-runnable without --clean. CHANGELOG entries for this + the CLI error/usage
consistency change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Follow-on to the CLI error/usage consistency pass — bring the associated-image
edit commands (label/macro/overview/thumbnail × remove/replace) in line with the
rest of the CLI (breaking, pre-1.0):

- Overwrite the output with -f/--force (was --overwrite, removed), matching
  convert/crop/downsample/region/extract.
- The replace aspect-ratio-guard bypass moves from --force to
  --allow-aspect-mismatch, so --force never means two different things.
- Remove the per-command -q/--quiet that shadowed the global flag with a
  different meaning. --quiet is now a single global flag with a -q short form
  that uniformly suppresses progress AND success/info output across every
  command (routed through a new infof() helper; previously only --to bif and the
  associated commands honored a quiet flag for their "wrote …" lines).
- Default output suffix is <stem>_edited<ext> (was _relabeled, misleading for
  non-label edits).

No aliases kept (per the single-letter-only rule). All unit + integration tests
pass; associated_test updated for the _edited suffix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously only downsample / crop (re-encode) / convert --factor showed a
progress bar (the only path through runEngineRetile). Make it consistent: every
write path now shows a tile-progress bar.

- retile engine: add an optional Spec.OnTileWritten hook, called per tile from
  the single sink-drain goroutine. All engine callers (downsample, crop,
  convert --factor, convert stitched/transcode/dzi/szi/dicom/ife) wire a bar
  through it. runEngineRetile drops the bespoke countingSink in favour of the
  hook.
- verbatim / manual-copy loops get direct per-tile counters: convert tile-copy
  (writeTIFFTileCopy), per-level transcode (transcodeLevel, drain goroutine),
  crop --lossless (writeLosslessL0 / *COGWSI), and --to bif (bifwriter.
  WritePyramid gains an onTile callback).
- new cmd/wsitools/progress.go: one nil-safe progressBar helper. Gated on
  --quiet AND an stderr-is-a-terminal check (stdlib os.ModeCharDevice), so bars
  never leak escape-codes into pipes/CI. mpb already suppresses non-TTY output;
  the explicit gate makes it deterministic and avoids spawning the render
  goroutine when not needed.

Tests: retile OnTileWritten hook (only successful writes counted); sumLevelTiles;
progressBar no-op safety + non-TTY-writes-nothing. Full convert/crop/transcode/
dicom/ife/bif/dzi integration suites pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cornish cornish merged commit 8535bae into main Jun 30, 2026
2 checks passed
@cornish cornish deleted the fix/cli-error-usage-consistency branch June 30, 2026 14:18
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.

1 participant