Define terminal failure presentation for invocation reporting

This commit is contained in:
2026-10-24 01:19:16 +00:00
parent 0869b17b43
commit 085c296d89

View File

@@ -3,9 +3,9 @@
Status: initial planning. Message categories, all four output modes, uniform Status: initial planning. Message categories, all four output modes, uniform
treatment of help and version, message prefixes, and OD-1's flag grammar and treatment of help and version, message prefixes, and OD-1's flag grammar and
scope (including independent Progress control) are selected. scope (including independent Progress control) are selected.
OD-2's unified reporting direction is selected. Exact API signatures, failure OD-2's unified reporting direction and the terminal failure model are selected.
presentation, retention, and delivery mechanics remain open. Implementation has Exact API signatures, failure explanation details, retention, and delivery
not started. mechanics remain open. Implementation has not started.
## Purpose ## Purpose
@@ -46,7 +46,8 @@ There is currently no shared verbosity policy or invocation reporter API.
Distinguish substantive application output from diagnostic message categories: Distinguish substantive application output from diagnostic message categories:
- **Substantive output (Normal):** The requested report or command result. - **Substantive output (Normal):** The requested report or command result.
- **Error:** The invocation failed and will return a non-zero status code. - **Error:** Terminal presentation of an unrecoverable invocation failure,
resulting in a non-zero status code.
- **Warning:** Something went wrong or deserves attention, but the invocation - **Warning:** Something went wrong or deserves attention, but the invocation
can still succeed. A recovered problem is a warning. can still succeed. A recovered problem is a warning.
- **Info:** Informational context and useful explanation, such as which profile - **Info:** Informational context and useful explanation, such as which profile
@@ -76,12 +77,9 @@ Applications and integrations are not required to generate messages in any
category. Enabling a category adds no output when there are no messages in it; category. Enabling a category adds no output when there are no messages in it;
other output remains subject to its own visibility rules. other output remains subject to its own visibility rules.
Error presentation is tied to invocation failure. Prefer deriving error Error presentation follows the terminal failure model below. Problems from
diagnostics from a failed outcome, which may carry detailed explanations. Avoid which the invocation recovers are warnings, even when an attempted operation
an unrestricted `Error(...)` reporting method that permits an error message failed internally.
followed by a successful outcome. The application still controls process exit
under the existing outcome contract; the returned outcome must consistently
represent the failure and its non-zero status.
Apply the same policy to help and version. There are no command-specific Apply the same policy to help and version. There are no command-specific
exceptions for successful output: exceptions for successful output:
@@ -107,6 +105,37 @@ Streaming Progress messages use the diagnostic channel so they do not corrupt
substantive output such as JSON or YAML. Progress presentation details remain substantive output such as JSON or YAML. Progress presentation details remain
part of the consumer API and delivery design below. part of the consumer API and delivery design below.
### Terminal failure model
During execution, applications can produce substantive output, Progress, Info,
Debug, and Warnings. An unrecoverable failure ends the handler by returning a
failed outcome. There is no standalone `report.Error(...)` method. Detailed
error explanations accompany the returned failure and are presented as part of
that terminal step.
CommandKit finalizes reporting, presents the terminal failure explanation, and
returns the non-zero outcome to the application entry point. It accepts no
further normal output for that invocation after terminal error presentation.
The same boundary applies to core routing and parsing failures that prevent
handler execution. The application entry point retains ownership of process
exit; CommandKit ends the invocation and returns its outcome.
For example, a handler returns immediately on an unrecoverable failure:
```go
result, err := performOperation()
if err != nil {
return commandkit.Failure(err)
}
// Continue normal reporting only after successful operation.
```
Output streamed before the failure remains visible according to its selected
mode; terminal failure does not withdraw earlier bytes. Deferred messages,
cleanup writes, and delivery failures must respect the end of normal reporting.
Their finalization and late-write behavior remain OD-4 details. A terminal
failure may have multiple explanatory records, all belonging to that failure.
## Selected flag grammar and scope ## Selected flag grammar and scope
### Mode selection and resets ### Mode selection and resets
@@ -300,10 +329,10 @@ diagnostic data for the handler to submit, independently of CommandKit.
The returned outcome owns the operation result: success, failure, or an The returned outcome owns the operation result: success, failure, or an
application domain classification. CommandKit presents a failed outcome through application domain classification. CommandKit presents a failed outcome through
the same reporting facility. Error explanations must be explicitly associated the same reporting facility as the terminal step. Error explanations belong to
with the failure they describe; an unrestricted `Error(...)` method that permits that returned failure, including rich upstream explanations. Typed diagnostic
success afterward is outside this direction. Typed upstream diagnostic submission submission must preserve this relationship instead of permitting independently
must preserve that relationship as well. emitted Error messages during normal execution.
Use the reporter as the common diagnostic submission path, replacing the earlier Use the reporter as the common diagnostic submission path, replacing the earlier
proposal to split submission between a reporter and `Outcome.Diagnostics`. proposal to split submission between a reporter and `Outcome.Diagnostics`.
@@ -349,13 +378,15 @@ rules.
4. Implement the selected behavior across core and the integrations. Preserve 4. Implement the selected behavior across core and the integrations. Preserve
upstream rendering and semantics while applying the chosen visibility policy. upstream rendering and semantics while applying the chosen visibility policy.
5. Verify classification, flag selection, suppression, retained diagnostics, 5. Verify classification, flag selection, suppression, retained diagnostics,
ordering, duplicate prevention, Error/non-zero-outcome consistency, debug ordering, duplicate prevention, terminal Error/non-zero-outcome consistency, debug
visibility, and write-failure handling with focused behavioral tests and visibility, and write-failure handling with focused behavioral tests and
maintained consumer examples. Cover mode resets, mixed canonical/alias maintained consumer examples. Cover mode resets, mixed canonical/alias
ordering, help and discovery contexts, and core parser events presented ordering, help and discovery contexts, and core parser events presented
according to the final mode. Cover explicit progress overrides, debug's according to the final mode. Cover explicit progress overrides, debug's
progress default, quiet suppression, progress aliases, message prefixes, progress default, quiet suppression, progress aliases, message prefixes,
and preservation of native multiline diagnostics. and preservation of native multiline diagnostics. Verify the end of normal
reporting after terminal error presentation, including deferred and late
writes under the selected OD-4 behavior.
6. Update GoDoc, the CLI reference, consumer guidance, and release documentation 6. Update GoDoc, the CLI reference, consumer guidance, and release documentation
when implemented. Review whether any resulting architectural change needs an when implemented. Review whether any resulting architectural change needs an
ADR; exact reporting APIs and flag syntax remain API/CLI contracts. ADR; exact reporting APIs and flag syntax remain API/CLI contracts.
@@ -364,12 +395,11 @@ rules.
### OD-3: Failure presentation and diagnostic retention ### OD-3: Failure presentation and diagnostic retention
How does the API enforce that Error diagnostics accompany a failed invocation The terminal failure model is selected above. How are detailed explanations
with a non-zero status, including application domain outcomes? How should attached to the returned failure, including application domain failures? How
failure explanations and the operation outcome be associated to avoid are recovered upstream problems represented as warnings while preserving their
inconsistent caller-supplied combinations? How are recovered upstream problems represented as warnings native context? Which contextual records belong to a terminal error explanation?
while preserving their native context? How are mixed upstream
Which contextual records belong to an error explanation? How are mixed upstream
diagnostic batches filtered while preserving useful native rendering? What is diagnostic batches filtered while preserving useful native rendering? What is
retained when presentation is suppressed, and how is duplicate presentation retained when presentation is suppressed, and how is duplicate presentation
prevented without hiding unrelated failures? prevented without hiding unrelated failures?
@@ -379,7 +409,9 @@ diagnostics? What presentation should streaming Progress use?
### OD-4: Delivery lifecycle and quiet execution ### OD-4: Delivery lifecycle and quiet execution
How are immediate and deferred messages ordered and finalized, including when How are immediate and deferred messages ordered and finalized, including when
the operation fails? How do callers observe and react to write failures? What the operation fails? How do deferred messages, cleanup writes, and attempts to
use the reporter after terminal failure respect the end of normal reporting?
How do callers observe and react to write failures? What
delivery state represents intentional suppression? Does quiet mode discard delivery state represents intentional suppression? Does quiet mode discard
rendered bytes or skip report rendering, and how does that choice preserve rendered bytes or skip report rendering, and how does that choice preserve
operation semantics and failure detection? Which streaming behavior becomes operation semantics and failure detection? Which streaming behavior becomes