[GH-ISSUE #113] Return reliable nonzero CLI exit status for structured operation failures #71

Closed
opened 2026-10-15 18:20:48 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @morluto on GitHub (Jul 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/113

Summary

Ensure every REA CLI command returns a nonzero process exit status when the requested operation fails, even when the failure is represented as valid structured JSON/TOON/YAML output.

Observed behavior in REA 1.3.0

Commands such as inventory-artifact and investigate-versions can return shell exit status 0 while output contains an operational failure, for example:

  • ArtifactOperationError / integrity_mismatch;
  • InvestigationWorkspaceError / disabled.

The envelope may itself serialize successfully, but serialization success is not operation success.

User problem

Shell scripts, CI, coding agents, and command runners conventionally use the process status as the primary success signal. Exit 0 with an embedded error can:

  • be mistaken for valid Evidence;
  • allow pipelines to continue;
  • overwrite prior reports;
  • produce false-positive verification;
  • require every caller to parse REA-specific envelopes before checking success.

Required semantics

Separate three concepts:

  1. command parsed and output encoded;
  2. requested operation succeeded;
  3. process successfully wrote the selected output format.

Suggested exit classes:

  • 0: requested operation succeeded;
  • nonzero stable code: invalid input or policy/permission failure;
  • nonzero stable code: analysis/provider/integrity failure;
  • nonzero stable code: cancellation or timeout;
  • nonzero stable code: output/serialization failure;
  • conventional signal-derived status where appropriate.

Exact numeric codes may remain simple, but they must be documented and stable enough for automation.

Structured output

On expected failure:

  • still emit one valid object in the selected format;
  • include the typed error contract from #100;
  • write machine-readable output to stdout when requested;
  • route incidental diagnostics/progress to stderr;
  • exit nonzero after output flush succeeds.

Broken pipes and serialization failures must not be reported as successful analysis.

Composition and pipeline requirements

  • Piped commands must preserve failure through pipefail-compatible use.
  • --full-output and filtered output must not change exit status.
  • A resumed investigate-versions run that fails before a checkpoint must return nonzero.
  • Partial/truncated success must have explicit documented semantics; truncation must not be conflated with execution failure.
  • Setup outcomes such as needs_human should have a deliberate documented status.

Acceptance criteria

  • Every CLI command has an explicit success/failure exit-status contract.
  • Expected operation failures exit nonzero in every output format.
  • Structured failure output remains valid and machine-readable.
  • Exit status is independent of --format, --full-output, filtering, and token limits.
  • Cancellation, timeout, permission failure, integrity mismatch, provider failure, and serialization failure are distinguishable.
  • Success with bounded/truncated evidence has documented status semantics.
  • Tests execute packaged CLI commands and assert both output and process status.
  • Shell pipeline examples use pipefail where relevant.
  • Documentation includes an exit-status table.
  • MCP behavior remains unaffected; this issue concerns terminal process semantics.

Non-goals

  • Printing raw stack traces.
  • Removing structured errors.
  • Assigning a unique numeric exit code to every internal exception.
  • Treating warnings or explicit unknown evidence as process failure when the requested operation completed truthfully.

Relationships

  • #100 defines structured error bodies.
  • #111 governs diagnostic detail preservation.
  • Verification tooling should treat this issue as required to prevent false green automation.
Originally created by @morluto on GitHub (Jul 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/113 ## Summary Ensure every REA CLI command returns a nonzero process exit status when the requested operation fails, even when the failure is represented as valid structured JSON/TOON/YAML output. ## Observed behavior in REA 1.3.0 Commands such as inventory-artifact and investigate-versions can return shell exit status 0 while output contains an operational failure, for example: - ArtifactOperationError / integrity_mismatch; - InvestigationWorkspaceError / disabled. The envelope may itself serialize successfully, but serialization success is not operation success. ## User problem Shell scripts, CI, coding agents, and command runners conventionally use the process status as the primary success signal. Exit 0 with an embedded error can: - be mistaken for valid Evidence; - allow pipelines to continue; - overwrite prior reports; - produce false-positive verification; - require every caller to parse REA-specific envelopes before checking success. ## Required semantics Separate three concepts: 1. command parsed and output encoded; 2. requested operation succeeded; 3. process successfully wrote the selected output format. Suggested exit classes: - 0: requested operation succeeded; - nonzero stable code: invalid input or policy/permission failure; - nonzero stable code: analysis/provider/integrity failure; - nonzero stable code: cancellation or timeout; - nonzero stable code: output/serialization failure; - conventional signal-derived status where appropriate. Exact numeric codes may remain simple, but they must be documented and stable enough for automation. ## Structured output On expected failure: - still emit one valid object in the selected format; - include the typed error contract from #100; - write machine-readable output to stdout when requested; - route incidental diagnostics/progress to stderr; - exit nonzero after output flush succeeds. Broken pipes and serialization failures must not be reported as successful analysis. ## Composition and pipeline requirements - Piped commands must preserve failure through pipefail-compatible use. - --full-output and filtered output must not change exit status. - A resumed investigate-versions run that fails before a checkpoint must return nonzero. - Partial/truncated success must have explicit documented semantics; truncation must not be conflated with execution failure. - Setup outcomes such as needs_human should have a deliberate documented status. ## Acceptance criteria - [ ] Every CLI command has an explicit success/failure exit-status contract. - [ ] Expected operation failures exit nonzero in every output format. - [ ] Structured failure output remains valid and machine-readable. - [ ] Exit status is independent of --format, --full-output, filtering, and token limits. - [ ] Cancellation, timeout, permission failure, integrity mismatch, provider failure, and serialization failure are distinguishable. - [ ] Success with bounded/truncated evidence has documented status semantics. - [ ] Tests execute packaged CLI commands and assert both output and process status. - [ ] Shell pipeline examples use pipefail where relevant. - [ ] Documentation includes an exit-status table. - [ ] MCP behavior remains unaffected; this issue concerns terminal process semantics. ## Non-goals - Printing raw stack traces. - Removing structured errors. - Assigning a unique numeric exit code to every internal exception. - Treating warnings or explicit unknown evidence as process failure when the requested operation completed truthfully. ## Relationships - #100 defines structured error bodies. - #111 governs diagnostic detail preservation. - Verification tooling should treat this issue as required to prevent false green automation.
bsakaguchi 2026-10-15 18:20:48 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#71
No description provided.