Clarify provider diagnostics and reporting edge cases
This commit is contained in:
@@ -7,8 +7,9 @@ OD-2's unified reporting direction, the terminal failure model, and application
|
||||
ownership of domain-specific error decisions are selected.
|
||||
OD-3's failure presentation and retention boundaries are selected.
|
||||
OD-4's delivery lifecycle, write-failure handling, and quiet-mode rendering are
|
||||
selected. The consumer API signatures and presentation-result model below are
|
||||
also selected. Architectural preparation is complete:
|
||||
selected. The consumer API signatures, presentation-result model, provider
|
||||
diagnostic boundary, fallback explanations, and rendering callback boundary
|
||||
below are also selected. Architectural preparation is complete:
|
||||
[ADR 0014](../adr/0014-invocation-reporting.md) is accepted, and the
|
||||
[architecture policy](../policy/architecture.md) is aligned. Implementation has
|
||||
not started; implementation, validation, and maintained consumer examples remain.
|
||||
@@ -167,6 +168,8 @@ 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 selected API below provides failure constructors for this purpose.
|
||||
When a failed outcome supplies no explanation, CommandKit supplies the generic
|
||||
fallback defined under terminal outcomes below.
|
||||
|
||||
Output streamed before the failure remains visible according to its selected
|
||||
mode; terminal failure does not withdraw earlier bytes. Deferred messages,
|
||||
@@ -544,6 +547,21 @@ reporter operations from interleaving with it. Rendering callbacks write through
|
||||
their supplied writer. Each complete categorized message, including its details,
|
||||
is likewise coordinated as one reporter operation.
|
||||
|
||||
Rendering callbacks use their supplied writer only during the callback. They may
|
||||
call rendering helpers that write through it. While a callback is running, it
|
||||
must not recursively submit messages, queue deferred messages, start another
|
||||
rendering operation, or write through a separate `Output()` handle belonging to
|
||||
the same invocation's reporter. Make additional reporter submissions before or
|
||||
after the callback. A callback must also avoid waiting for another goroutine to
|
||||
submit through that reporter, since the submission may be waiting for the
|
||||
callback to finish.
|
||||
|
||||
This boundary applies to `RenderOutput`, immediate and deferred message details,
|
||||
and terminal explanation details. Ordinary concurrent reporter calls remain
|
||||
supported and serialized. Keeping each rendering operation together motivates
|
||||
the boundary; it does not prescribe a lock implementation or promise runtime
|
||||
detection of recursive calls.
|
||||
|
||||
Message strings are literal; consumers use `fmt.Sprintf` when formatting is
|
||||
needed. Initially omit parallel `Infof`, `Warnf`, and similar methods. CommandKit
|
||||
formats the opening message with its category's prefix and a terminating newline.
|
||||
@@ -651,6 +669,26 @@ The named renderers above have signature `func(io.Writer) error` and preserve th
|
||||
owning library's safe diagnostic formatting. They run during terminal delivery,
|
||||
not when constructing the outcome.
|
||||
|
||||
Before terminal delivery, supply the explanation `Command failed.` when a
|
||||
non-zero outcome has an empty `Explanation.Message` and no non-nil callback in
|
||||
`Explanation.Details`. This produces `ERROR: Command failed.` in every mode,
|
||||
including quiet, and becomes the explanation retained in the returned outcome.
|
||||
Adding the fallback leaves classification, status, and cause unchanged;
|
||||
presentation failures still follow OD-4's rules. The fallback is based on the
|
||||
failed outcome and absent explanation, without deriving text from `Cause.Error()`.
|
||||
|
||||
An empty heading with a non-nil detail renderer is an explicitly supplied
|
||||
explanation. Trust that renderer to provide its content. Do not buffer or replay
|
||||
it to decide whether the explanation is sufficiently informative, and do not
|
||||
add the fallback merely because it writes no bytes.
|
||||
|
||||
| Returned outcome | Terminal presentation |
|
||||
| --- | --- |
|
||||
| `Failure("")` | Generic fallback, operational classification and status `1`. |
|
||||
| `Domain("validation", 3)` | Generic fallback, domain classification and status `3`. |
|
||||
| `Failure("").WithCause(err)` | Generic fallback; the supplied cause remains available without automatic rendering. |
|
||||
| `Failure("", writeNativeFailure)` | Native explanation without an added generic heading. |
|
||||
|
||||
`Cause` is optional. `WithCause` returns a modified outcome value, replacing the
|
||||
cause without changing the classification, status, or explanation. For example:
|
||||
|
||||
@@ -672,6 +710,42 @@ failures are recorded separately in `Presentation`. The returned outcome retains
|
||||
its terminal explanation and optional cause, with other retention limited to the
|
||||
presentation needs described above.
|
||||
|
||||
### Provider-returned diagnostic data
|
||||
|
||||
Providers return values and diagnostic data without needing a reporter parameter.
|
||||
Retain `Acquired[T]` with separate fields for independent messages and failure
|
||||
explanations:
|
||||
|
||||
```go
|
||||
type Acquired[T any] struct {
|
||||
Value T
|
||||
Diagnostics []Diagnostic
|
||||
Explanation Explanation
|
||||
}
|
||||
```
|
||||
|
||||
`Diagnostics` carries independent, nonterminal messages. `Diagnostic` and
|
||||
`Severity` remain passive data types for those messages, with each diagnostic
|
||||
carrying its `Severity` and a `Write func(io.Writer) error` renderer. Adapt their
|
||||
contracts to the nonterminal reporting categories. Integrations submit the
|
||||
records through the corresponding reporter methods, including the deferred view
|
||||
where appropriate. Removing `Outcome.Diagnostics` removes a submission path;
|
||||
provider-returned records remain available for the integration to submit.
|
||||
|
||||
`Explanation` carries context to attach when the integration returns a failed
|
||||
outcome. Terminal Error content uses this field rather than an independently
|
||||
submitted diagnostic. An upstream warning that helps explain the failure may
|
||||
belong in the explanation; unrelated warnings remain in `Diagnostics` and follow
|
||||
their ordinary visibility rules. Adapters preserve this distinction and useful
|
||||
native formatting when translating mixed upstream batches, instead of assigning
|
||||
the whole batch its highest severity.
|
||||
|
||||
Providers may return acquired data alongside a Go error. The owning integration
|
||||
chooses the command outcome, attaches any terminal explanation, and decides which
|
||||
cause to preserve. Returning diagnostic data does not itself emit messages or
|
||||
select the invocation outcome. Diagnostic renderers follow the same callback
|
||||
boundary as other details when invoked through the reporter.
|
||||
|
||||
### Presentation observations and closed reporters
|
||||
|
||||
```go
|
||||
@@ -786,7 +860,9 @@ rules.
|
||||
terminal failure with an explicit explanation and no Go error cause.
|
||||
Include simple and structured failure construction without early emission,
|
||||
optional cause transport independent of operator text, and an integration
|
||||
returning both a substantive report and a failure.
|
||||
returning both a substantive report and a failure. Include provider-returned
|
||||
independent warnings and terminal context, unexplained failures receiving the
|
||||
fallback, and rendering helpers using only the supplied callback writer.
|
||||
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`.
|
||||
@@ -796,6 +872,10 @@ rules.
|
||||
Account for flag collisions and document changed public contracts.
|
||||
4. Implement the selected behavior across core and the integrations. Preserve
|
||||
upstream rendering and semantics while applying the chosen visibility policy.
|
||||
Adapt provider-returned `Acquired[T]`, `Diagnostic`, and `Severity` contracts
|
||||
to independent nonterminal messages and separate terminal explanations.
|
||||
Replace whole-batch severity promotion with deliberate separation of failure
|
||||
context and unrelated messages. Providers remain independent of the reporter.
|
||||
5. Verify classification, flag selection, suppression, terminal explanations,
|
||||
ordering, duplicate prevention, terminal Error/non-zero-outcome consistency, debug
|
||||
visibility, and write-failure handling with focused behavioral tests and
|
||||
@@ -833,6 +913,19 @@ rules.
|
||||
processing and subsequent presentation failures, including wrapped errors
|
||||
inspected with `errors.Is` and `errors.As`. Verify causes alone do not produce
|
||||
messages or change statuses or visibility.
|
||||
Verify provider-returned data remains unpresented until submitted by the
|
||||
integration, including data returned alongside an error. Cover mixed batches
|
||||
where terminal context remains visible in quiet mode and unrelated warnings
|
||||
remain suppressed. Verify generic fallback presentation and retention for
|
||||
failed outcomes with no message or non-nil detail renderer, with and without
|
||||
a cause. Check unchanged classifications, statuses, and causes when fallback
|
||||
delivery succeeds, and existing presentation-failure rules when it fails.
|
||||
Cover native details with an empty heading, including a renderer that writes
|
||||
no bytes, without adding a fallback or replaying callbacks to inspect content.
|
||||
Exercise callback helpers using the supplied writer, messages submitted before
|
||||
and after rendering, and ordinary concurrent submissions serialized around a
|
||||
complete rendering operation. Document the callback boundary without requiring
|
||||
runtime detection of recursive reporter use.
|
||||
6. Update GoDoc, the CLI reference, consumer guidance, and release documentation
|
||||
when implemented. Exact reporting APIs and flag syntax remain API/CLI
|
||||
contracts.
|
||||
|
||||
Reference in New Issue
Block a user