Clarify application error handling and reporting ownership
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
Status: initial planning. Message categories, all four output modes, uniform
|
||||
treatment of help and version, message prefixes, and OD-1's flag grammar and
|
||||
scope (including independent Progress control) are selected.
|
||||
OD-2's unified reporting direction and the terminal failure model are selected.
|
||||
OD-2's unified reporting direction, the terminal failure model, and application
|
||||
ownership of error handling are selected.
|
||||
Exact API signatures, failure explanation details, retention, and delivery
|
||||
mechanics remain open. Implementation has not started.
|
||||
|
||||
@@ -19,6 +20,30 @@ straightforward. Design reporting conveniences around the shared output policy
|
||||
and invocation lifecycle. Applications continue to own their report content,
|
||||
domain behavior, and operation outcomes.
|
||||
|
||||
## CLI presentation and error-handling ownership
|
||||
|
||||
Applications decide how to handle errors from their operations: recover, retry,
|
||||
continue silently, report a Warning, or end the invocation with a failure.
|
||||
A Go `error` does not determine a CLI message category. Warnings may describe
|
||||
issues with or without an underlying Go error, and handling an error does not
|
||||
require emitting a message.
|
||||
|
||||
CommandKit handles the presentation the application requests: message category,
|
||||
visibility, formatting, timing, and delivery. For terminal application failures,
|
||||
the application supplies a non-zero outcome and an operator-facing explanation.
|
||||
Reporting does not require the underlying Go error or undertake its tracking,
|
||||
recovery, or identity preservation.
|
||||
|
||||
A convenience helper that explicitly presents `err.Error()` as a Warning could
|
||||
fit this boundary. Such a helper would only convert the supplied error to a
|
||||
message at the application's request; its inclusion and signature remain open.
|
||||
|
||||
CommandKit retains responsibility for handling its own errors, including
|
||||
routing, parsing, and reporting failures. Integration-owned commands similarly
|
||||
adapt their upstream APIs into deliberate command outcomes and presentations.
|
||||
This boundary governs application error handling; ordinary Go error returns
|
||||
from CommandKit APIs and writers remain available where appropriate.
|
||||
|
||||
## Current baseline
|
||||
|
||||
[`Streams` and `Invocation`](../../identity.go) expose caller-selected output
|
||||
@@ -49,7 +74,7 @@ Distinguish substantive application output from diagnostic message categories:
|
||||
- **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
|
||||
can still succeed. A recovered problem is a warning.
|
||||
can still succeed. The application chooses whether to report such an issue.
|
||||
- **Info:** Informational context and useful explanation, such as which profile
|
||||
was selected or a final operation summary.
|
||||
- **Progress:** Streaming updates about work underway, such as items processed.
|
||||
@@ -77,9 +102,8 @@ 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;
|
||||
other output remains subject to its own visibility rules.
|
||||
|
||||
Error presentation follows the terminal failure model below. Problems from
|
||||
which the invocation recovers are warnings, even when an attempted operation
|
||||
failed internally.
|
||||
Error presentation follows the terminal failure model below. An application
|
||||
may report a recovered problem as a Warning or continue without a message.
|
||||
|
||||
Apply the same policy to help and version. There are no command-specific
|
||||
exceptions for successful output:
|
||||
@@ -120,15 +144,12 @@ 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.
|
||||
```
|
||||
For example, if an export operation fails and the application decides it cannot
|
||||
continue, the handler returns a non-zero outcome with an explicit explanation
|
||||
such as "Unable to export the requested report." The application can choose to
|
||||
include detail from a Go error in that explanation. CommandKit presents the
|
||||
supplied explanation without automatically deriving text from an application
|
||||
error. The exact failure-construction API remains open under OD-3.
|
||||
|
||||
Output streamed before the failure remains visible according to its selected
|
||||
mode; terminal failure does not withdraw earlier bytes. Deferred messages,
|
||||
@@ -295,9 +316,9 @@ output is not part of the proposed direction.
|
||||
|
||||
Keep errors understandable in every mode, including source locations and
|
||||
related explanatory context. Unrelated warnings and informational messages
|
||||
remain subject to the selected mode. Retain suppressed diagnostics for
|
||||
programmatic inspection rather than equating suppression with loss of evidence.
|
||||
The exact representation of retained and delivered diagnostics remains open.
|
||||
remain subject to the selected mode. Whether to retain submitted messages for
|
||||
programmatic inspection, including suppressed messages, remains open under
|
||||
OD-3. This concerns presentation records, not application error tracking.
|
||||
|
||||
## Selected consumer reporting API direction
|
||||
|
||||
@@ -332,7 +353,8 @@ application domain classification. CommandKit presents a failed outcome through
|
||||
the same reporting facility as the terminal step. Error explanations belong to
|
||||
that returned failure, including rich upstream explanations. Typed diagnostic
|
||||
submission must preserve this relationship instead of permitting independently
|
||||
emitted Error messages during normal execution.
|
||||
emitted Error messages during normal execution. Application failures carry
|
||||
explicit status and presentation content; they do not require a Go error cause.
|
||||
|
||||
Use the reporter as the common diagnostic submission path, replacing the earlier
|
||||
proposal to split submission between a reporter and `Outcome.Diagnostics`.
|
||||
@@ -354,9 +376,12 @@ those capabilities through the shared CommandKit presentation policy.
|
||||
|
||||
Support consistent reporting of ConfigKit errors and warnings as its adopted
|
||||
public API evolves. This roadmap does not assume that a future warning API
|
||||
already exists or prescribe its upstream shape. Preserve useful native
|
||||
diagnostic detail and supported error identity, and coordinate returned errors
|
||||
with diagnostics that already explain them.
|
||||
already exists or prescribe its upstream shape. Integration-owned commands
|
||||
select the outcome and submit useful native diagnostic detail for presentation.
|
||||
Core presents those records under the shared policy; it does not infer an
|
||||
application's recovery decisions or classify arbitrary Go errors. Applications
|
||||
using upstream libraries directly retain the same choice over outcomes and
|
||||
messages as for their other operations.
|
||||
|
||||
Debug output follows the same upstream disclosure and safe-rendering contracts.
|
||||
Enabling debug does not authorize secret disclosure or bypass owning-library
|
||||
@@ -368,6 +393,8 @@ rules.
|
||||
immediate and deferred diagnostics, failure after partial output, help and
|
||||
version, and integration diagnostics in every mode. Include applications that
|
||||
emit no Progress messages and the distinction between Info and Progress.
|
||||
Cover silent recovery, an explicit Warning with or without a Go error, and a
|
||||
terminal failure with an explicit explanation and no Go error cause.
|
||||
2. Review current diagnostic batching, parsing, help, outcome presentation, and
|
||||
writer ownership to identify the smallest shared changes. Include invocation
|
||||
failures that occur before a handler receives its `Invocation`.
|
||||
@@ -388,23 +415,33 @@ rules.
|
||||
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
|
||||
when implemented. Review whether any resulting architectural change needs an
|
||||
ADR; exact reporting APIs and flag syntax remain API/CLI contracts.
|
||||
when implemented. Reconcile the selected error-handling boundary with
|
||||
ADR 0005's existing outcome and error-identity commitments before changing
|
||||
those contracts. Record any resulting architectural change in a new ADR;
|
||||
exact reporting APIs and flag syntax remain API/CLI contracts.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
### OD-3: Failure presentation and diagnostic retention
|
||||
|
||||
The terminal failure model is selected above. How are detailed explanations
|
||||
attached to the returned failure, including application domain failures? How
|
||||
are recovered upstream problems represented as warnings while preserving their
|
||||
native context? Which contextual records belong to a terminal error explanation?
|
||||
How are mixed upstream
|
||||
diagnostic batches filtered while preserving useful native rendering? What is
|
||||
retained when presentation is suppressed, and how is duplicate presentation
|
||||
prevented without hiding unrelated failures?
|
||||
How do adapters apply the selected prefixes to mixed or already-labelled native
|
||||
diagnostics? What presentation should streaming Progress use?
|
||||
The terminal failure model and application error-handling boundary are selected
|
||||
above. The remaining questions concern explicit presentation content:
|
||||
|
||||
- How does a handler supply a non-zero outcome with a simple explanation or
|
||||
multiple structured explanatory records, including application domain failures?
|
||||
- How do callers and integration adapters identify the context belonging to a
|
||||
terminal explanation, and present mixed diagnostic batches while preserving
|
||||
useful native rendering and applying visibility to independent messages?
|
||||
- Which submitted messages, if any, are retained for programmatic inspection,
|
||||
including when suppressed? How is that observation exposed separately from
|
||||
message submission?
|
||||
- How is duplicate presentation avoided, and how do adapters apply prefixes to
|
||||
mixed or already-labelled native diagnostics?
|
||||
- What presentation should streaming Progress use? Is a convenience helper for
|
||||
explicitly presenting `err.Error()` as a Warning useful enough to include?
|
||||
|
||||
Application error classification, recovery, and cause tracking are outside
|
||||
these questions. Delivery failures produced by reporting remain under OD-4.
|
||||
|
||||
### OD-4: Delivery lifecycle and quiet execution
|
||||
|
||||
|
||||
Reference in New Issue
Block a user